- 投稿日:2020-09-18T20:17:47+09:00
VPCエンドポイントを試してみた
vpcエンドポイントのハンズオンを体験したので、概要と作成方法の記録です。
勉強途中のため一部理解が追いついていない部分がありますが、ご了承ください。vpcエンドポイントとは
vpcエンドポイントは、グローバルIPを持つAWSサービスに対して、vpc内から直接アクセスするための出口のこと。
オンプレだと、専用線で自社サーバと、別地域のサーバやらストレージを接続するイメージです。(うん百万かかるのに・・・)
今回は、プライベートサブネット内のインスタンスから、S3へ直接アクセスするための、vpcエンドポイントを作成します。
以下の順に進んでいきますので、よろしくお願いいたします。
間違っている箇所があればコメントで教えていただけると大変助かります利用環境
今までに作成したVPCやサブネット、インスタンスをそのまま利用しました。
下図の赤線ルートでS3へアクセスできることが目的です。(黒線はVPCエンドポイントを使用しない場合のアクセス例)
S3の作成
今までS3は作成してこなかったため、最初にS3の作成を行います。
AWSマネジメントコンソールから「S3」と検索し、「S3マネジメントコンソール」に移動します。
S3マネジメントコンソールに移動したら、「バケットの作成」を選択します。
私はいくつかバケットを作成しているのでバケット名が表示されていますが、初回であれば何も表示されません。
S3バケットに名前をつけたら、今回は他に設定をしないので「作成」を選択します。
S3バケット名は一意の値である必要があるため、日付等を名前の後に付与すると良いようです。
IAMロールの作成・インスタンスの割当
続いて、インスタンスがS3へアクセスするためのIAMロールを作成します。
(S3を作成しただけでは使えません!!まずはインスタンスがS3へアクセスできるよう権限設定をします)AWSマネジメントコンソールから「IAM」と検索し、「IAMマネジメントコンソール」に移動します。
IAMマネジメントコンソールの左ペイン、「ロール」を選択し、「ロールの作成」を選択します。
ユースケースは「EC2」を選択し「次のステップ」を選択します。
「AmazonS3FullAccess」を選択し、「次のステップ」を選択します。
※「ポリシーのフィルタ」で「S3」を入力すると良きです。
設定しなくても大丈夫ですが、「Name」キーの設定を行いました。
「ロール名」、「ロールの説明」を入力し、「ロールの作成」を選択します。
※ロール名は先ほどの「Name」キーと同様の値にしています。ロールの説明は適当でも大丈夫です。
ここまでで、S3へのアクセス権を持った、IAMロールの完成です。
続けて、作成したIAMロールをインスタンスへ割り当てます。
「EC2マネジメントコンソール」に移動して、インスタンスを選択後、「アクション」、「インスタンスの設定」、「IAMロールの割り当て/置換」を選択します。
なお、インスタンスが停止していると割り当てに失敗しますので、起動状態でお願いします。
下の画面はインスタンスが停止しているので、この後失敗します。
先ほど作成したロールを選択して、「適用」を選択します。
これでIAMロールに準じたアクセス権限がインスタンスにされたことになります。
今回は、「AmazonS3FullAccess」がインスタンスに付与されたことになります。また、プライベートサブネット内のインスタンスに割り当てたので、VPCエンドポイントもNATゲートウェイもない今の状態では、S3へは接続できません。
実際にプライベートサブネット内のインスタンスに接続して確認してみます。
# 自分のPCから $ ssh ec2-user@18.177.121.50 -i my-key.pem # パブリックサブネットのインスタンスから [ec2-user@10.0.1.10 ~]$ ssh ec2-user@10.0.2.10 -i DBserver.pem # プライベートサブネットのインスタンスから [ec2-user@10.0.2.10 ~]$ aws s3 ls下図のようにプロンプトが戻ってきませんので、「Ctrl」+「C」でAbortしましょう。
VPCエンドポイントの作成・設定
続いてVPCエンドポイントを作成します。
VPCダッシュボードから、左ペインの「エンドポイント」を選択します。
「S3」でフィルタをかけて、表示されたサービスを選択します。
vpcは自身で作成したvpcを選択します。
プライベートサブネットに属しているルートテーブルを選択します。
ポリシーは変更せず、「エンドポイントの作成」をすると完成です!!
先ほどと同様の手順で確認をしてみると。。。
「aws s3 ls」コマンドで応答が帰ってこなかったため、以下コマンドを使用しています。
$ aws s3 ls --region ap-northeast-1少し補足
VPCエンドポイントには2種類あり、今回使用したのは無料のGateway型です。
Privatelink型は有料だそうです。
名前 実装方法 Gateway型 エンドポイントポリシーをルートテーブルに設定することで直接アクセスする Privatelink型 サブネットがエンドポイント用のIPを持ち、それをDNSが名前解決することでルーティングする 参考文献
- これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座(SAA-C02試験対応版
- そのトラフィック、NATゲートウェイを通す必要ありますか?適切な経路で不要なデータ処理料金は削減しましょう
- AWSの公式ドキュメント VPCエンドポイント
最後までお付き合いいただきありがとうございました
- 投稿日:2020-09-18T18:50:05+09:00
【AWS SOA】認証情報レポートの備忘録
はじめに
SOAの試験にあたって、IAM認証情報レポートに関する問題が問題集で出題された。SAAでは見なかったもので、備忘録としてIAM認証情報レポートとは何かを簡単に記載したい。
認証情報レポートとは?
ユーザーと、ユーザーの各種認証情報 (パスワード、アクセスキー、MFA デバイスなど) のステータスが示された認証情報レポートを生成し、ダウンロード可能。
認証情報レポートがどこから入手できるかで、IAMから取れるということを覚えておこう。入手方法
IAM>認証情報レポートを開き、レポートをダウンロードを押すとレポートが出る。
参考
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_getting-report.html
- 投稿日:2020-09-18T18:39:39+09:00
AWS Elastic Beanstalk に swap 設定(永続化も忘れずに)
AWS Elastic Beanstalk のウェブコンソールではメモリ容量はインスタンスタイプ設定でできるものの swap 設定はできません。
なので、ebextension に書くことで設定します。swapを設定するところまではネットに転がっていたのですが、永続化まで考慮に入れている記事がなかったのでこの記事を書きました。
swaponコマンドで実行したものは再起動すると設定が巻き戻ってしまうので、fstabファイルに設定を書いておきます。書き方
アプリケーションのトップディレクトリに
.ebextensions
ディレクトリを作成し、その中にswap.config
とでも名前をつけて以下の内容を配置します。ebextensions/swap.configcommands: 000_create_file: test: test ! -e /swapfile command: dd if=/dev/zero of=/swapfile bs=1M count=1024 && chmod 600 /swapfile 001_mkswap: command: mkswap /swapfile ignoreErrors: true 002_swapon: command: swapon /swapfile ignoreErrors: true 003_fstab: test: test `grep -c swap /etc/fstab` -eq 0 command: echo "/swapfile swap swap defaults 0 0" >> /etc/fstabステップ順に軽い解説をしておきます
- 000_create_file
- /swapfile という名前の0埋めされたファイルを作ります
- swapはメモリの拡張のためにファイルを使う方式なので、ストレージサイズがタイトな場合には予め増量しておいた方が良いと思います。筆者の環境ではサーバに8G、使用中4G程度あったので、2Gのスワップを割り当てると残りがかなりタイトになってしまう状態でした
test ! -e /swapfile
はファイルがなかったら作るためのshellコマンドです- 001_mkswap
- ファイルを元にswap領域を作成します
- ignoreErrors しないとすでに転換が済んでいる場合にエラーが出るので入っています
- 002_swapon
- スワップ領域を使用します
- 003_fstab
- 以下に記述
fstabに記述がすでにある場合には次のデプロイで書き込む必要がないので、存在チェックをしています。
test `grep -c swap /etc/fstab` -eq 0
grep -c swap /etc/fstab
がfstabファイルに存在するswap
と書かれている行数で、-eq 0
はそれが0行であることをチェックしていますfstab の中身は最終的に以下のようになります。
[ec2-user@ip-172-31-26-7 ~]$ cat /etc/fstab # LABEL=/ / ext4 defaults,noatime 1 1 tmpfs /dev/shm tmpfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 sysfs /sys sysfs defaults 0 0 proc /proc proc defaults 0 0 /swapfile swap swap defaults 0 0おまけ
ebextension はデプロイしないといけないので動作確認の負荷が高いです。
test コマンドの実行などは手元環境で試した方が楽です。こちらのebextensionの内容の確認をしたいケース。
003_fstab: test: test `grep -c swap /etc/fstab` -eq 0 command: echo "/swapfile swap swap defaults 0 0" >> /etc/fstab以下のようにシェルのワンライナーでだいたい確認することができます。
if test `grep -c swap /etc/fstab` -eq 0 ; then echo "/swapfile swap swap defaults 0 0" >> /etc/fstab; fi
- 投稿日:2020-09-18T17:29:58+09:00
AWSのまずはやっておくべきセキュリティ対策
AWSのまずはやっておくべきセキュリティ対策として、基本的なことだが 大事なことなのでまとめておこうと思います。
AWS Identity and Access Management
IAMによる認証
- rootユーザには、強力なパスワードと多要素認証(MFA)を設定
- 基本的には、rootユーザを使用しない
- rootユーザのAccess Keyが発行されていた場合は削除する
- IAMユーザのパスワードポリシーには強力なものを設定
- IAMユーザのパスワードやAccess Key/Secret Access Keyは定期的にローテーションする
- 認証情報の利用状況はIAMのCredential Report機能で定期的に確認
IAMによる権限設定
- 全てのアクセスはデフォルトで拒否(Deny)となっているため、必要な権限のみ明示的に許可(Allow)設定を行う
- アクセス権限の優先度は
暗黙的なDeny(デフォルトDeny) < 明示的なAllow < 明示的なDeny
- IAMポリシーは最小限のアクセス権を付与
監査
- AWS CloudTrailによる証跡取得を行う
- 誰が、いつ、どのような操作(AWS Console、CLI、API等)したかを記録
- AWS CloudTrail自体の料金は無料
- AWS ConfigによるAWSリソースの設定を記録し評価を行う
- AWSリソースの変更履歴、構成情報を管理
- AWS Config RulesでAWSリソースがあるべき状態になっているかを自動評価
- 例)Security GroupでSSHをフルオープンにしていないか
- 例)公開状態になっているS3はないか
- 例)全てのIAMユーザでMFAが有効になっているか
IAMロール
- EC2にはIAMロールを利用する
- AWSサービスに対してAWS操作権限を付与し、IAMユーザの認証情報をOSやアプリに持たせる必要がなく、認証情報の漏洩リスクを低減
- 自動的に認証情報(Access Key/Secret Access Key)がローテーションされる
- 認証情報はAWS Security Token Service(STS)により生成
- IAMロールを使えるものは全てIAMロールを利用
- オンプレからAWSリソースを操作する場合等、致し方ない場合のみIAMユーザを利用
- IAMユーザやアクセスキーは共有しない
- git-secretsを使用しクレデンシャル情報の漏洩防止
S3 Access Management
- 必要以上に公開範囲の広いポリシーやACLを設定しない
- EC2やAWSサービスからのアクセスはIAMロールで行う
- 外部へ開放されているバケットを定期的にチェックする
- AWS Trusted Advisor
- AWS IAM Access Analyzer(Access Analyzer for S3)
発見的統制
- 各種AWSサービスのログを有効化する
- CloudTrail:誰が、いつ、どのような操作(AWS Console、CLI、API等)したかを記録
- VPC Flow Logs:VPCのネットワークインタフェース間のIPトラフィックをキャプチャ
- Lambda:Lambda Functionに関するエラー出力、標準出力等のログを収集
- CloudWatch Logs Agent:EC2上で動作するOS、ミドルウェア、アプリケーション等のログをCloudWatchへ収集
データ保護
- 保存時のデータ暗号化(Encryption at Rest)
- サーバサイド暗号化(SSE)ではAWS Key Management Service(KMS)キーを使用し暗号化
- クライアントサイド暗号化(CSE)ではKMSでCustomer Master Key(CMK)を使用し暗号化
- 通信の暗号化(Encryption in Transit)
- SSL通信を利用
- AWS Certificate Managerで証明書を発行(無料)、自動管理
- CloudFrontとELB間をHTTPSにし、ELBをSSH Terminationとする
- DB接続情報やクレデンシャル等はセキュアに保管する
- AWS Systems Manager Parameter Store
- AWS Secrets Manager
- 投稿日:2020-09-18T17:29:58+09:00
AWSのやっておくべきセキュリティ対策
AWSのやっておくべきセキュリティ対策として、基本的なことだが 大事なことなのでまとめておこうと思います。
AWS Identity and Access Management
IAMによる認証
- rootユーザには、強力なパスワードと多要素認証(MFA)を設定
- 基本的には、rootユーザを使用しない
- rootユーザのAccess Keyが発行されていた場合は削除する
- IAMユーザのパスワードポリシーには強力なものを設定
- IAMユーザのパスワードやAccess Key/Secret Access Keyは定期的にローテーションする
- 認証情報の利用状況はIAMのCredential Report機能で定期的に確認
IAMによる権限設定
- 全てのアクセスはデフォルトで拒否(Deny)となっているため、必要な権限のみ明示的に許可(Allow)設定を行う
- アクセス権限の優先度は
暗黙的なDeny(デフォルトDeny) < 明示的なAllow < 明示的なDeny
- IAMポリシーは最小限のアクセス権を付与
監査
- AWS CloudTrailによる証跡取得を行う
- 誰が、いつ、どのような操作(AWS Console、CLI、API等)したかを記録
- AWS CloudTrail自体の料金は無料
- AWS ConfigによるAWSリソースの設定を記録し評価を行う
- AWSリソースの変更履歴、構成情報を管理
- AWS Config RulesでAWSリソースがあるべき状態になっているかを自動評価
- 例)Security GroupでSSHをフルオープンにしていないか
- 例)公開状態になっているS3はないか
- 例)全てのIAMユーザでMFAが有効になっているか
IAMロール
- EC2にはIAMロールを利用する
- AWSサービスに対してAWS操作権限を付与し、IAMユーザの認証情報をOSやアプリに持たせる必要がなく、認証情報の漏洩リスクを低減
- 自動的に認証情報(Access Key/Secret Access Key)がローテーションされる
- 認証情報はAWS Security Token Service(STS)により生成
- IAMロールを使えるものは全てIAMロールを利用
- オンプレからAWSリソースを操作する場合等、致し方ない場合のみIAMユーザを利用
- IAMユーザやアクセスキーは共有しない
- git-secretsを使用しクレデンシャル情報の漏洩防止
S3 Access Management
- 必要以上に公開範囲の広いポリシーやACLを設定しない
- EC2やAWSサービスからのアクセスはIAMロールで行う
- 外部へ開放されているバケットを定期的にチェックする
- AWS Trusted Advisor
- AWS IAM Access Analyzer(Access Analyzer for S3)
発見的統制
- 各種AWSサービスのログを有効化する
- CloudTrail:誰が、いつ、どのような操作(AWS Console、CLI、API等)したかを記録
- VPC Flow Logs:VPCのネットワークインタフェース間のIPトラフィックをキャプチャ
- Lambda:Lambda Functionに関するエラー出力、標準出力等のログを収集
- CloudWatch Logs Agent:EC2上で動作するOS、ミドルウェア、アプリケーション等のログをCloudWatchへ収集
データ保護
- 保存時のデータ暗号化(Encryption at Rest)
- サーバサイド暗号化(SSE)ではAWS Key Management Service(KMS)キーを使用し暗号化
- クライアントサイド暗号化(CSE)ではKMSでCustomer Master Key(CMK)を使用し暗号化
- 通信の暗号化(Encryption in Transit)
- SSL通信を利用
- AWS Certificate Managerで証明書を発行(無料)、自動管理
- CloudFrontとELB間をHTTPSにし、ELBをSSH Terminationとする
- DB接続情報やクレデンシャル等はセキュアに保管する
- AWS Systems Manager Parameter Store
- AWS Secrets Manager
- 投稿日:2020-09-18T17:22:43+09:00
DiscordのWebhooksをurllib経由でたたいて簡単自動発言ボット作成
概要
AWS Lambda の Python 3.7 ランタイムを使ってDiscordのWebhook URL を叩くと 403 でうまいこと叩けずに困った。
原因を調べたらどうやらUAをチェックしているらしく、UAが urllib だとNG。( 試しに使った curl はOK )
Discordのライブラリを入れればいいんだろうけど、Lambdaという都合上、ほか依存ライブラリ追加したくない。
UAをcurlに偽装することでうまいこと叩けた。よかったよかった。
反省
- うまくいくパターンとだめなパターンの差分はHTTPヘッダをみよ。
- APIがコケる場合にはちゃんとステータス値とレスポンスボディとマニュアルをみよ。
参照
Python3のスクリプトでjsonをPOSTする - Qiita
詳細
What is Webhooks
Discordにおいて、なにかあったら自動で特定のチャンネルにメッセージを送りたい。
なんでも Webhookってのが作られるらしく、それならシンプルにJSONをポストするだけでそういうことができる。
(本当はDMを送りたかったんだけど、そっちはAPI経由になってだるそうなんでヤメ)How to get Webhook URL
たぶん管理者権限がいる。
- チャンネルの右側に表示されているギアをクリック
- 左のメニューから「連携サービス」をクリック
- 「ウェブフック」とあるのでそこの「詳細」 or 「ウェブフックを確認」をクリック
- 「新しいウェブフック」をクリック、ポストされるときの名前を指定し、チャンネルを指定
- 「ウェブフックURLをコピー」をクリックすればOK
試す
とりあえず POST はオオゴトなんでまずは GET から。curlを使って試す。
$ curl -v https://discordapp.com/api/webhooks/xxxxxxxx 略 < HTTP/2 200 略 {"type": 1, "id": "xxxx", "name": "xxxxx", "avatar": null, "channel_id": "xxxxxx", "guild_id": "xxxxxx", "application_id": null, "token": "xxxxxx"}OK。エンドポイントが正しくあることは確認できた。
POSTを試す。
$ curl -v -X POST -H "Content-Type: application/json" -d '{"content":"ふぁらおからウェブフック経由のポストで参上"}' https://discordapp.com/api/webhooks/xxxxxxxxでOK。
Pythonのコードから試す
以下で試せばOK。試しに
urllib.request.Request
の第3パラメータのUser-Agent
を削除してみてほしい。それだと弾かれてしまう。url = "https://discordapp.com/api/webhooks/xxxxxxxx" method = "POST" headers = {"Content-Type" : "application/json"} obj = {"content" : "ふぁらおからウェブフック経由のポストで参上"} json_data = json.dumps(obj).encode("utf-8") request = urllib.request.Request( url, json_data, {"User-Agent": "curl/7.64.1", "Content-Type" : "application/json"}, method ) with urllib.request.urlopen(request) as response: response_body = response.read().decode("utf-8") print(response_body)
- 投稿日:2020-09-18T17:02:04+09:00
AWS Copilotとecspressoの違いを調べてみた
結論
- 下記「背景」のようなケースの場合は、ecspressoまたは類似ツールを使ったほうが事故は少ない
- コンテナやAWSやっていき勢、PoCなど速度が必要なケースはAWS Copilotを使ってみて慣れていくのはアリ
- というより、双方のツールは目指すところが全然違うので比較対象として論じること自体にちょっと無理がある
前提
本稿で記載している「ECS」は「ECS on Fargate」であり、「ECS on EC2」ではありません。
双方のツールを軽く触れて書いた記事なので、細かい機能について把握していないものもあると思います。背景
これまでいくつかのAWSを使用したプロジェクトのインフラ管理にTerraformをオールインワンツールとして採用してきました。
しかし、システムの規模が大きくなるにつれてTerraformではどうしても取り回しの鈍さが出てくるケースが増えてきたため、アプリケーションレベルのデプロイコントロールはECSに特化したCLIに乗り換えたほうが良いのでは…と思い至り、調査した結果を記事にしました。ECSとは
ECS is 何?という方は、AWSの中の人として大人気なトリ先生のスライドを見るといいです。
https://pages.awscloud.com/rs/112-TZM-766/images/A-1.pdf※本稿では触れないCLIツールも上記スライド内でPros/Consが紹介されています
AWS Copilotとは
AWS ECS CLIの後継サービスでAWS謹製。
デフォルトでモダンかつプロダクションレディなインフラ構築をサポートしてくれるらしい。リポジトリ
https://github.com/aws/copilot-cli
特徴
- VPC、サブネット、ロードバランサー、デプロイパイプライン、ストレージなどのクラウドリソースを管理できる
- 上記の細かい設定はデフォルトでいい感じになっているらしい
- 生きたOSSプロジェクトなので気になる点はIssueやPRを出せる
- 単一バイナリ
- 本番や開発など環境ごとの設定をマニフェストファイルとしてYAMLで管理できる
- Dockerfileだけあればアプリケーションを最低限実行するために必要なものをインタラクティブにデプロイしてくれる
- ECS Service Discoveryを比較的簡単に使用できる
- 内部的にCloudFormationのコードを生成しているためAWSに関する対応が幅広い
- サイドカー構成は現時点では事前定義された構成(FireLens)しか使用できなさそう
- 既存のリソースはVPC周りしかインポートできなさそう
- リポジトリにWikiはあるが、限定的な情報しか書いてないので使うなら手探りになりそう
ecspressoとは
面白法人カヤック社が開発したECSデプロイツール。
飲み物の「エスプレッソ」からもじったとのこと。
ECSサービスやECSタスクのコントロールに特化しているため、AWS CLIなどを使って頑張るより手軽にデプロイ操作をコントロールできる。
いくつかのCI/CDツールとの親和性もあるため、CI/CD自動化にも組み込みやすく、小規模なサービスならこれだけで事足りるケースも多い。
利用者も一定数いるため、初期導入についてはググれば十分な情報を得ることができる。リポジトリ
https://github.com/kayac/ecspresso
特徴
- タスク定義を含めて開発用リポジトリで管理できる
- みんな大好きGolang製
- 生きたOSSプロジェクトなので気になる点はIssueやPRを出せる
- 単一バイナリ
- サイドカー構成のデプロイも可能
- go-configと併用すると環境変数の展開もできる
- ツールで出来ることが限定されているので開発者が軽い気持ちで使っても大事故が起こりにくい
比較一覧表
No 項目 AWS Copilot ecspresso 1 ALBの作成 ○ ☓ 1 NLBの作成 ☓ ☓ 1 ECSクラスターの作成 ○ ☓ 1 ECSサービスの作成 ○ ○ 1 ECSタスク定義の作成 ○ ○ 1 ECSタスクのスケーリング操作 ○ ○ 1 ECSタスクのロールバック ☓ ○ 1 Fargate Spot ☓ ○ 1 Blue/Green Deploy対応 ? ○ 1 サイドカーのデプロイ △ ○ 1 brew install ○ ○ 1 Task Execution IAM Roleの管理 ○ ☓ 1 Task IAM Roleの管理 ○ ☓ 1 DRY RUN ☓ ○ 1 YAML ○ ○ 1 Github Actions連携 ☓ ○ 1 Circle CI連携 ☓ ○ 1 Codeシリーズ連携 ○ ○
- 投稿日:2020-09-18T14:14:12+09:00
APIとは
見てくださった方々に正しい情報を伝えられるように頑張りますが、初投稿なので細かい所は大目に見てくださいっ。
定義
APIとは「Application Programming Interface」の頭文字を取ったものです。
「Application」→アプリケーション、ソフトウェア
「Programming」→プログラム
「Interface」→「何か」と「何か」を繋ぐもの
以上を大雑把に言うと「アプリケーション、ソフトウェアとプログラムを繋ぐもの」ということになります。
例えるなら、パソコンと周辺機器をつなげるUSBも役割的には同じ役割です。
APIの場合ソフトウェア同士をつなげます。つまり、APIを使うと異なるソフトウェアやサービス間で認証機能を共有したり、チャット機能を共有したり、片方から数値データを取り込み、別のプログラムでそのデータを解析したりできるようになります。メリット
・アプリケーションの開発時間やコストの削減が可能
・セキュリティの向上
・最新情報を簡単に取得できる他にもあると思いますが、以上がAPIの利点と言えます。
アプリケーションの開発時間やコストの削減が可能
APIを使うことによって自分で1からプログラムを組む必要がなくなり、プログラムの開発時間を省略できるようになります。開発になれていないエンジニアでも簡単にアプリケーション開発が可能になります。
セキュリティの向上
色々な世の中のサービスの中で会員登録時にGoogleアカウントやFaceboolアカウントと連携することで登録できたという経験があると思いますがこれはAPIのおかげでできています。
この連携により簡単に会員登録できるようになる他に、自社でセキュリティレベルの高い会員登録システムを入れるよりも、すでにあるセキュリティレベルの高い会員システムを導入する方がユーザーも安心してサービスを使うことができます。最新情報を簡単に取得できる
APIを使えばそれぞれの最新情報をこちら側から取得しなくても取得、利用できるようになります。
例えば、自分のサイトでAmazonや楽天などの商品を売っている場合、販売価格や商品情報が変わった時にも自動で変更されるようになります。WEBAPI
WEBAPIとはweb上に公開されていて、外部から呼び出して利用することができるAPIです。
WEBAPIの例
・Amazon
・ぐるなび
・楽天
・Yahoo一般的には企業のwebサイトから登録をしてAPIを取得します。各々のAPIの使い方は今回また別の機会で紹介できたらなと思います。
WEBAPIを使うにあたって
実際にAPIを使うときには注意点があります。
・APIキー(アクセスキー)
・APIシークレットキー
この2つを使うときに取得するのですがAPIキーはログインの際のID名にあたる部分、APIシークレットはパスワードのようなものです。なので大切に管理しなければなりません。この2つが第三者や外部に漏れてしまうと情報を買い替えられたり、勝手に送金や出金をされてしまう場合もあります。なのでパスワードや他の権利関連のものは大切に管理しましょう。終わりに
https://data.wingarc.com/what-is-api-16084/4
https://www.internetacademy.jp/it/programming/javascript/how-to-use-web-api.htmlこちらのサイトを参考にさせていただきました。
簡単になりましたが大体APIとはこんな感じなんだなと思っていただければ幸いです。
詳しい各々のAPIの紹介はこちらの方が紹介しているQiitaが分かりやすくておすすめです。
- 投稿日:2020-09-18T13:15:14+09:00
AWS Systems Managerを用いてEC2上のコマンドを動かしてみた
こんにちは。streampackのfadoです。厳しい暑さが続いておりますがみなさん、いかがお過ごしでしょうか。まだまだ油断は禁物ですのでうがいと手洗いを忘れないようにしましょう。さて、今回は表題にも書きました通り、
AWS Systems Manager
を利用し、AWS Lambda
及びAmazon API Gateway
と連携したシステムでAmazon EC2
インスタンス上でコマンドを実行させる方法を簡単に説明していきたいと思います。注意事項
- Linuxコマンド及び
AWS Lambda
,Amazon API Gateway
,AWS Systems Manager
の知見がある方を対象にしています。AWS Lambda
はPython3で記載しています。- ffmpegのRTMP送信先は
AWS Elemental MediaLive
->AWS Elemental MediaPackage
にしていますがスコープ外ですのでセットアップ等は割愛させていただきます。リソース
- Amazon EC2 (以下 EC2)
- AWS Systems Manager(以下 SSM)
- AWS Lambda (以下 Lambda)
- Amazon API Gateway(以下 API Gateway)
- AWS IAM (IAM ロールとIAM ポリシー)
手順
EC2
- OSは
Amazon Linux 2
を使っています。AWS Systems Manager
エージェントとffmpegが動く環境であればどのOSでも問題ありません。AmazonSSMManagedInstanceCore
ポリシーがアタッチされたIAM ロール
を対象EC2
インスタンスにつけます。AmazonSSMManagedInstanceCore
はEC2
インスタンスがSSM
のメイン機能を取り扱えるように許可してくれるポリシーです。- 例ではffmpegコマンドを利用しますので事前にインストールしておきましょう。
- 動画はフリー素材を使っています。
SSM
AWS Systems Manager
コンソールにて「インスタンスとノード」 -> 「マネージドインスタンス」のタブで対象EC2インスタンスが登録されていることを確認します。表示に出ていない場合はEC2
にアタッチされているロールにAmazonSSMManagedInstanceCore
ポリシーが漏れている可能性があります。
Lambda
Lambda
のIAM ロール
にAWS Systems Manager
のssm:SendCommand
とssm:ListCommandInvocations
アクションを利用しているのでこの二つのアクションが含まれるポリシーを付けます。Lambda
のIAM ロール
専用のポリシーにしたいので、インランポリシーでの作成になります。関数コードは次の通りです。
lambda_handler.pyimport boto3 import time import json apigw = boto3.client('apigateway') ssm = boto3.client('ssm') ## 対象インスタンスを定義 instance_id = ['i-XXXXXXXXX'] ## 実行するコマンドを定義 start_cmd = "/usr/local/bin/ffmpeg -re -stream_loop -1 -i /home/ec2-user/media/bbb_sunflower_1080p_30fps_normal.mp4 -c:v copy -c:a aac -flags +loop-global_header -f flv rtmp://XX.XX.XX.XX:1935/test/live < /dev/null > /tmp/ffmpeg.log 2>&1 &" stop_cmd = "/usr/bin/killall ffmpeg" def lambda_handler(event, context): try: ## API GatewayのURL pathによって実行するコマンドを区別 api_path = event['path'] if "start" in api_path: cmd_to_execute = {'commands': [start_cmd]} elif "stop" in api_path: cmd_to_execute = {'commands': [stop_cmd]} else: return "No matches,exiting..." ### send-commandを実行 response = ssm.send_command( DocumentName = "AWS-RunShellScript", InstanceIds = instance_id, Comment = 'Executing ffmpeg command...', TimeoutSeconds = 600, Parameters = cmd_to_execute ) command_id = response['Command']['CommandId'] ## send_commandのCommandIdid値が取得できるまで数秒かかることもあるため5秒間隔をおく time.sleep(5) ## ステータスを取得 list_invocations = ssm.list_command_invocations( CommandId = command_id, Details = True ) ### Api Gatewayに渡すレスポンスを定義 body = list_invocations['CommandInvocations'][0]['Status'] return { 'statusCode': 200, 'headers': {'Content-Type': 'application/json'}, 'body': body } except Exception as e: raise e詳細な説明は省きますが上記は
API Gateway
から送られてきたURLを判別し、対象EC2
インスタンスに対しstartまたはstopコマンドの実行命令を送ります。コマンド実行が成功ならSuccess,失敗ならFailedのレスポンスが戻ってくる流れとなっています。API Gateway
次のように設定します。リソース名は分かりやすいものにしましょう。
尚、メソッドはGETではなくPOSTにします。APIのURLを叩くだけで実行されないようにするためです。
プロトコル メソッド リソース名 REST POST /start REST POST /stop メソッドを設定する際に「Lambda プロキシ統合の使用」にチェックを入れます。これは
API Gateway
が受信リクエストをLambda
関数の入力eventパラメータにマッピングさせるためです。検証
startコマンド
1.設定したstart用APIでPOSTメソッドを用いて実行します。「Success」レスポンスが返ってきたら問題なくコマンドが実行されたことになります。「Failed」レスポンスの場合は、EC2インスタンスのamazon-ssm-agent.logをご確認ください。
$ curl -X POST https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/ffmpeg/start Success2.
EC2
インスタンス上でffmpegプロセスが起動できていることを確認できました。$ ps axu|grep ffmpeg root 3119 9.9 1.0 91388 21100 ? S 01:23 0:00 /usr/local/bin/ffmpeg -re -stream_loop -1 -i /home/ec2-user/media/bbb_sunflower_1080p_30fps_normal.mp4 -c:v copy -c:a aac -flags +loop-global_header -f flv rtmp://54.249.218.4:1935/test/live ec2-user 3121 0.0 0.1 110536 2236 pts/0 S+ 01:23 0:00 grep --color=auto ffmpeg3.配信が問題なくできていることも確認できました。
(配信はスコープ外なのでできていなくてもffmpegプロセスさえ動いていれば問題ありません)stopコマンド
1.設定したstop用APIでPOSTメソッドを用いて実行します。「Success」レスポンスが返ってきたら問題なくコマンドが実行されたことになります。「Failed」レスポンスの場合は、EC2インスタンスのamazon-ssm-agent.logをご確認ください。
$ curl -X POST https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/ffmpeg/stop Success2.
EC2
インスタンス上でffmpegプロセスが起動できていることを確認できました。$ ps axu|grep ffmpeg ec2-user 3108 0.0 0.1 110536 2236 pts/0 S+ 01:22 0:00 grep --color=auto ffmpeg
SSM
からのコマンド実行に問題がないかEC2
インスタンスのログでも確認することができます。/var/log/amazon/ssm/amazon-ssm-agent.logの一部
}, "documentStatus": "Success", "documentTraceOutput": "", "runtimeStatus": { "aws:runShellScript": { "status": "Success", "code": 0, "name": "aws:runShellScript", "output": "", "startDateTime": "2020-09-17T16:08:17.477Z", "endDateTime": "2020-09-17T16:08:17.488Z", "outputS3BucketName": "", "outputS3KeyPrefix": "", "stepName": "", "standardOutput": "", "standardError": "" }結論
AWS Systems Manager
,AWS Lambda
とAmazon API Gateway
を活用すればEC2
インスタンス上でコマンドを簡単に実行させることができます。今回は単純な処理を例に挙げて説明しましたが踏み込んだコマンドを実行するスクリプトを用意すればさらに高度な処理ができ、かつその実行結果を表示させることも可能です。それではまた次回!参考文献
https://aws.amazon.com/jp/systems-manager/
https://aws.amazon.com/jp/lambda/
https://aws.amazon.com/jp/api-gateway/
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
- 投稿日:2020-09-18T12:30:39+09:00
しくじり / id_rsaを上書きしてしまった話
AWS C9でアプリケーション開発を行う際、SSH接続がgithubとEC2インスタンスでこんがらがった話。
C9上でgit管理している場合
githubをリポジトリとしてssh接続する際は~/environment/.ssh
フォルダに置いておくと思う(当時無知識だったため、そのままid_rsaという名前にした)
ここで登録する際に名前を例えばid_rsa_githubなどに変更するか、もしくはディレクトリを切ってgithubを指定しておけば後々詰まることもなかっただろうそして開発がある程度終了し
EC2インスタンスに接続するためのid_rsaを同じフォルダに上書きしてしまっていた今までgithubにssh接続出来ていたものが、突然Permission denied (publickey).と怒られるようになる
上書きしてしまったのものは仕方ないので、こういった場合はgithubのssh接続を再登録すればOK
その際、ちゃんとディレクトリを切るなり、ファイル名を変更するなりして
.ssh/config
ファイルの中のパスを指定してあげましょう。
- 投稿日:2020-09-18T11:43:55+09:00
Amazon SESの1日の送信制限を引き上げる方法
SESを利用していて、これからも同じようなことがありそうなので忘れないようにまとめておきます。
SESとは?
SESとはAmazon Simple Email Serviceの略で、デベロッパーが任意のアプリケーションでメールを送信できるようにするメール配信サービスです。
特徴としては、従量課金制、導入コストが低い等が挙げられています。
また、SESには無料枠があり月62000通までは無料で使用できます(EC2からメールを送信する場合)。
詳しい料金設定は以下を参考にして下さい。
SESの料金について1日の送信制限の上限を上げたい
SESを利用する場合、デフォルトで送信できるメールの数が制限されいています。
なので大勢のユーザーに一斉にEメールを送りたいが、この申請をしていないと1日の送信制限に引っかかってしまい、送信できないなんてことが起きてしまいます。
なので以下に手順をまとめていきます。
1. AWSマネジメントコンソールにサインイン
2. 左上のサービスからSES(Simple Email Service)の設定画面へ
3. Sending Statisticsを押し、 Your Amazon SES Sending Limitsの
Sending Quotaを確認ここで現在の1日あたりの送信クォータが確認できます。
※画像では既に上限を引き上げているため50000となっていますが、デフォルトは200となっています。
4. 上限を引き上げたい場合は、右上のサポートからサポートセンターへ
7. 下に入力欄が出てくるので必要な項目を入力
ここで入力する項目は、以下になります。
・AWSアカウントID
・送信制限の引き上げをリクエストする AWS リージョン
・制限タイプ:希望する一日あたりの送信クォータ or 希望する最大送信レート
・新しい制限値
・Eメールメッセージタイプ(システム通知など該当するものを選択)
・ウェブサイトURL(必須ではないが、あったほうがいい)
・申請理由の説明項目の入力が完了したら送信。
ここまで終えれば基本的に24時間以内にAWSから返答があります。
まとめ
覚えといて損はないし、1回やってみると案外あっという間に終わったのでいい経験だった。
- 投稿日:2020-09-18T11:15:54+09:00
Slash Commandsで自分が使用している端末のグローバルIPは取得できるのか【API Gateway + Lambda(Go)】
はじめに
こんにちは。先月AWS ChatbotからRDSを操作していて、とても簡単にSlackから実行できて感動したので、第2弾です!今回はSlackから自分のグローバルIPを取得できるのかを、試してみました!
結論
残念ながら、Slackから自分のグローバルIPは取得できませんでした。
Slackで自分のグローバルIPを取得するべく、Slash CommandsというSlackのapiと、AWSのAPI Gateway、Lambdaを使って試みたので、その過程について備忘録です。
方法検討
自分のグローバルIPを取得して、それを引数としてLambdaを実行したかったので、AWSを使う方針で進めていきます。
調査したところ、SlackからLambdaを実行する方法を2つ見つけました。
- API Gatewayを使う方法(Slash Commandsの作成)
- AWS Chatbotを使う方法
API Gatewayはアクセス元のグローバルIPを取得できるというのを知ったので、今回はAPI Gatewayを使う方法(Slash Commandsの作成)で実装することにしました!
構成図
構成は下図の通りです。
ちなみに、Slash commandsは3000ms以内に応答を返す必要があるので、処理時間が長いものに関しては先にSlackに応答を返す必要があるみたいです。今回はアクセス元IPを返すだけなので、こちらの構成で実装しました。
参考:https://api.slack.com/interactivity/slash-commandsやってみる
Lambda関数の作成
今回はチャンネルを識別し、指定チャンネルから実行されていれば、アクセス元のグローバルIPを返すというLambda関数を作りました。
チャンネルを識別する意図としては、Slash Commandsは、ワークスペース内の全チャンネル、全DMで使えるもので、チャンネルを指定することができません。今回作成するSlash CommandsはグローバルIPを返すだけなので、どこで実行できても問題はないのですが、実際には指定したプライベートチャンネルのメンバーのみしか実行できないようにしたかったので、実行チャンネルを識別し、実行権限があるのかを判断する処理を入れています。
IAMロール
特別必要な権限はないので、基本的なLambdaアクセス権限をアタッチしたロールを使用します。
Slackから送られるデータと構造
Slackから送られるデータと構造は下記の通りです。
※ Valueは削除しています。本来はそれぞれ値が入っています。
※ 後述のAPI Gatewayのマッピングテンプレートを使用した場合の構造です。{ "querystring":{ "api_app_id":"", "channel_id":"", "channel_name":"", "command":"", "response_url":"", "team_domain":"", "team_id":"", "text":"", "token":"", "trigger_id":"", "user_id":"", "user_name":"" }, "source_ip":"" }ソースコード
package main import ( "github.com/aws/aws-lambda-go/lambda" "os" ) type MyEvent struct { Querystring Querystring `json:"querystring"` SourceIp string `json:"source_ip"` } type Querystring struct { ChannelId string `json:"channel_id"` } /************************** 処理実行 **************************/ func run(event MyEvent) (interface{}, error) { // os.Getenv()でLambdaの環境変数を取得 if event.Querystring.ChannelId == os.Getenv("channelId") { return event.SourceIp, nil } res := "実行権限がありません。" return res, nil } /************************** メイン **************************/ func main() { lambda.Start(run) }API Gatewayの作成
API Gatewayの作成を行います。
POSTメソッドを作成し、先ほど作成したLambda関数を紐付けます。そして、マッピングテンプレートの設定をしていきます。
[統合リクエスト]をクリックします。最下部にあるマッピングテンプレートを開き、リクエスト本文のパススルーはテンプレートが定義されていない場合 (推奨)を選択します。そして、[マッピングテンプレートの追加]をクリックします。
[マッピングテンプレートの追加]を押したら出てくるテキストボックスに
application/x-www-form-urlencoded
を入力、保存します。テンプレートの入力フォームが出てくるので、下記のマッピングテンプレートを貼り付け、[保存]をクリックします。
【マッピングテンプレート】
#set($rawAPIData = $input.path('$')) ## escape any quotes #set($rawAPIData = $rawAPIData.replace('"', '\"')) ## first we get the number of "&" in the string, this tells us if there is more than one key value pair #set($countAmpersands = $rawAPIData.length() - $rawAPIData.replace("&", "").length()) ## if there are no "&" at all then we have only one key value pair. ## we append an ampersand to the string so that we can tokenise it the same way as multiple kv pairs. ## the "empty" kv pair to the right of the ampersand will be ignored anyway. #if ($countAmpersands == 0) #set($rawPostData = $rawAPIData + "&") #end ## now we tokenise using the ampersand(s) #set($tokenisedAmpersand = $rawAPIData.split("&")) ## we set up a variable to hold the valid key value pairs #set($tokenisedEquals = []) ## now we set up a loop to find the valid key value pairs, which must contain only one "=" #foreach( $kvPair in $tokenisedAmpersand ) #set($countEquals = $kvPair.length() - $kvPair.replace("=", "").length()) #if ($countEquals == 1) #set($kvTokenised = $kvPair.split("=")) #if ($kvTokenised[0].length() > 0) ## we found a valid key value pair. add it to the list. #set($devNull = $tokenisedEquals.add($kvPair)) #end #end #end { "querystring" : { #foreach( $kvPair in $tokenisedEquals ) ## finally we output the JSON for this pair and append a comma if this isn't the last pair #set($kvTokenised = $kvPair.split("=")) #if($kvTokenised.size() == 2 && $kvTokenised[1].length() > 0) #set($kvValue = $kvTokenised[1]) #else #set($kvValue = "") #end #if( $foreach.hasNext ) #set($itemDelimiter = ",") #else #set($itemDelimiter = "") #end "$kvTokenised[0]" : "$kvValue"$itemDelimiter #end }, "source_ip" : "$context.identity.sourceIp" }最後にリソースのデプロイを行い、発行されたURLをコピーしておきます。
Slash Commandsの作成
Slack appの作成
Slack apiからSlack appを作成していきます。
[Create New App]をクリックするとAppの作成画面に遷移します。
ここで、Slack Appの名前とAppを実行したいワークスペースを選択します。
そして、[Create App]をクリックするとSlack Appが完成します。Slash commandsの作成
Appの設定ページに移動して、Slash commandsを作成します。
左側のメニューから[Slash commands]を選択し、[Create New Commands]をクリックします。
次に、Slackから送信するコマンド名、前述のAPI Gatewayで取得したリクエストURL、説明文の3つを入力します。今回は、
/get_ip
というコマンド名を設定しました。今回は引数を入力しないのでヒントは入れませんでしたが、引数など入力時の補足がある場合はUsage Hintに入力しておきます。Escape channels, users, and links sent to your appにチェックを入れることで、引数にユーザ名を入れる時に、ユーザ名だけではなくユニークなユーザIDも送ることができ、アカウントを識別できるそうです。今回はアカウントの識別は不要なので、チェックは入れませんでした。
それぞれ入力完了後、[Save]をクリックすると、Slash commandsが完成します。
Botの名前設定
このままAppのインストールに進むと、(App名)にはインストールするボットユーザーがありません。というエラーが出て、Appをインストールできなかったので、Appの設定ページから、Botを作成します。
ちなみに、App名が小文字英数字の場合は、自動でBotが設定されるみたいので、初期値が入っていればこのフローは不要です。わたしはIP取得マンというApp名にしていたためボットユーザが作られなかったのだと思われます。
左側のメニューから[App Home]を選択し、Your App's Presence in Slackの[Edit]をクリックします。
Botの表示名とユーザ名を入力して[Add]をクリックすると、Botの名前が設定されます。
Appのインストール
いよいよAppのインストールです。
左側のメニューから[Install App]を選択し、[Install App to Workspace]をクリックします。
作成したAppが指定したワークスペースにアクセスするのを許可すると、グローバルIPを取得するコマンドの完成です。
実行結果
実行方法
今回作成したコマンド
/get_ip
をメッセージとして送信します。指定チャンネルから実行した場合
指定チャンネルから実行した場合のレスポンスは次の通りです。
IPアドレスが返ってきました!!!
ただ、自分のグローバルIPを調べてみると・・・違う。。
これはSlackのグローバルIPアドレスですね。。。残念ながら、自分のグローバルIPアドレスを取得することはできませんでした。
指定外のチャンネルから実行した場合
ちなみに、指定外のチャンネルから実行した場合のレスポンスは次の通りです。
これで、実行チャンネルを識別し、指定チャンネル外からは実行できないことが確認できました!
おわりに
結果、SlackからグローバルIPを取得することはできませんでしたが、SlackのIPは取得することができました。ただ、実行する度に違うIPアドレスが返ってくることも確認できました。今回とは関係ないですが、Slackは複数のグローバルIPアドレスを持っていることがわかりました。
前回に引き続き、SlackからLambdaを実行してみましたが、AWS Chatbotと比較してSlash commandsの良いところは個人DMで使えるというところかなと感じました。反対に、Slash commandsの場合は処理時間が3000msを越えるものは、まず応答を返すようにしないといけないところは少し面倒かな、、と思いました。
今回は、残念な結果に終わってしまったので、また違う方法を考えます。SlackからグローバルIPを取得するいい方法があるよっていう方いらっしゃいましたら、教えていただけると嬉しいです!
参考
- 投稿日:2020-09-18T10:33:34+09:00
AWS ECS ~ demo
1.CloudFormation で環境を準備する
入力する箇所は、次のとおりで他の内容はデフォルトとする。
キー バリュー スタックの名前 任意 MasterUserName 任意(後でDBで使う。) MasterUserPassword 任意(後でDBで使う) { "AWSTemplateFormatVersion": "2010-09-09", "Description": "VPC Template For Multi-AZ", "Parameters": { "MasterUserName": { "Description": "RDS master user name", "Type": "String" }, "MasterUserPassword": { "Description": "RDS master user password", "Type": "String" } }, "Resources": { "VPC": { "Type" : "AWS::EC2::VPC", "Properties" : { "CidrBlock" : "10.0.0.0/16", "InstanceTenancy" : "default", "EnableDnsSupport" : "true", "EnableDnsHostnames" : "false", "Tags" : [ { "Key": "Name", "Value": "SimplechatVPC" } ] } }, "eip": { "Type" : "AWS::EC2::EIP", "Properties" : { "Domain" : "vpc" } }, "subnetPub1": { "Type" : "AWS::EC2::Subnet", "Properties" : { "CidrBlock" : "10.0.0.0/24", "AvailabilityZone" : { "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]}, "VpcId" : { "Ref": "VPC" }, "Tags" : [ { "Key": "Name", "Value": "Public-Subnet-1" } ] } }, "subnetPub2": { "Type" : "AWS::EC2::Subnet", "Properties" : { "CidrBlock" : "10.0.1.0/24", "AvailabilityZone" : { "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]}, "VpcId" : { "Ref": "VPC" }, "Tags" : [ { "Key": "Name", "Value": "Public-Subnet-2" } ] } }, "subnetPrv1": { "Type" : "AWS::EC2::Subnet", "Properties" : { "CidrBlock" : "10.0.2.0/24", "AvailabilityZone" : { "Fn::Select" : [ "0", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]}, "VpcId" : { "Ref": "VPC" }, "Tags" : [ { "Key": "Name", "Value": "Private-Subnet-1" } ] } }, "subnetPrv2": { "Type" : "AWS::EC2::Subnet", "Properties" : { "CidrBlock" : "10.0.3.0/24", "AvailabilityZone" : { "Fn::Select" : [ "1", { "Fn::GetAZs" : { "Ref" : "AWS::Region" }}]}, "VpcId" : { "Ref": "VPC" }, "Tags" : [ { "Key": "Name", "Value": "Private-Subnet-2" } ] } }, "Nat": { "Type" : "AWS::EC2::NatGateway", "Properties" : { "AllocationId" : { "Fn::GetAtt" : ["eip", "AllocationId"] }, "SubnetId" : { "Ref" : "subnetPub1" } }, "DependsOn" : "eip" }, "IGW": { "Type" : "AWS::EC2::InternetGateway", "Properties" : { "Tags" : [ { "Key": "Name", "Value": "Simplechat-IG" } ] } }, "RouteTablePublic": { "Type" : "AWS::EC2::RouteTable", "Properties" : { "VpcId" : { "Ref": "VPC" }, "Tags" : [ { "Key": "Name", "Value": "Public-RT" } ] } }, "RouteTablePrivate": { "Type" : "AWS::EC2::RouteTable", "Properties" : { "VpcId" : { "Ref": "VPC" }, "Tags" : [ { "Key": "Name", "Value": "Private-RT" } ] } }, "gw": { "Type" : "AWS::EC2::VPCGatewayAttachment", "Properties" : { "VpcId" : { "Ref": "VPC" }, "InternetGatewayId" : { "Ref": "IGW" } } }, "subnetRoutePub1": { "Type" : "AWS::EC2::SubnetRouteTableAssociation", "Properties" : { "RouteTableId" : { "Ref": "RouteTablePublic" }, "SubnetId" : { "Ref": "subnetPub1" } } }, "subnetRoutePub2": { "Type" : "AWS::EC2::SubnetRouteTableAssociation", "Properties" : { "RouteTableId" : { "Ref": "RouteTablePublic" }, "SubnetId" : { "Ref": "subnetPub2" } } }, "subnetRoutePrv1": { "Type" : "AWS::EC2::SubnetRouteTableAssociation", "Properties" : { "RouteTableId" : { "Ref": "RouteTablePrivate" }, "SubnetId" : { "Ref": "subnetPrv1" } } }, "subnetRoutePrv2": { "Type" : "AWS::EC2::SubnetRouteTableAssociation", "Properties" : { "RouteTableId" : { "Ref": "RouteTablePrivate" }, "SubnetId" : { "Ref": "subnetPrv2" } } }, "routePublic": { "Type" : "AWS::EC2::Route", "Properties" : { "DestinationCidrBlock" : "0.0.0.0/0", "RouteTableId" : { "Ref": "RouteTablePublic" }, "GatewayId" : { "Ref": "IGW" } }, "DependsOn" : "gw" }, "routePrivate": { "Type" : "AWS::EC2::Route", "Properties" : { "DestinationCidrBlock" : "0.0.0.0/0", "RouteTableId" : { "Ref": "RouteTablePrivate" }, "NatGatewayId" : { "Ref" : "Nat" } }, "DependsOn" : [ "Nat" , "subnetRoutePrv1", "subnetRoutePrv2" ] }, "LoadBalancerSecurityGroup": { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription": "simplechat_lb_sg", "GroupName" : "simplechat_lb_sg", "VpcId": { "Ref" : "VPC" }, "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "CidrIp" : "0.0.0.0/0" } ] } }, "WebServerSecurityGroup": { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription": "simplechat_web_sg", "GroupName" : "simplechat_web_sg", "VpcId": { "Ref" : "VPC" }, "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "80", "ToPort" : "80", "SourceSecurityGroupId" : { "Ref" : "LoadBalancerSecurityGroup" } } ] } }, "RDSSecurityGroup" : { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "simplechat_db_sg", "GroupName" : "simplechat_db_sg", "VpcId" : { "Ref" : "VPC" }, "SecurityGroupIngress" : [ { "IpProtocol" : "tcp", "FromPort" : "3306", "ToPort" : "3306", "SourceSecurityGroupId" : { "Ref" : "WebServerSecurityGroup" } } ] } }, "DbSubnetGroup": { "Type": "AWS::RDS::DBSubnetGroup", "Properties": { "DBSubnetGroupName": "simplechat_db_subnet", "DBSubnetGroupDescription": "simplechat_db_subnet", "SubnetIds": [ {"Ref": "subnetPrv1"}, {"Ref": "subnetPrv2"} ] } }, "DBParameterGroup": { "Type": "AWS::RDS::DBParameterGroup", "Properties": { "Description": "simplechat parameter group", "Family": "mysql5.7", "Parameters": { "character_set_client": "utf8mb4", "character_set_connection": "utf8mb4", "character_set_database": "utf8mb4", "character_set_results": "utf8mb4", "character_set_server": "utf8mb4", "collation_connection": "utf8mb4_bin", "collation_server": "utf8mb4_bin" } } }, "DbInstance": { "Type": "AWS::RDS::DBInstance", "Properties": { "DBInstanceIdentifier": "simplechat-ecs-db", "Engine": "MySQL", "EngineVersion": "5.7.22", "AllocatedStorage": "5", "MasterUsername": { "Ref": "MasterUserName" }, "MasterUserPassword": { "Ref": "MasterUserPassword" }, "DBInstanceClass": "db.t2.micro", "DBSubnetGroupName": { "Ref": "DbSubnetGroup" }, "DBParameterGroupName": { "Ref": "DBParameterGroup" }, "VPCSecurityGroups": [ { "Ref": "RDSSecurityGroup"} ] } }, "ALB" : { "Type" : "AWS::ElasticLoadBalancingV2::LoadBalancer", "Properties" : { "LoadBalancerAttributes" : [ { "Key" : "access_logs.s3.enabled", "Value" : "false" }, { "Key" : "deletion_protection.enabled", "Value" : "false" }, { "Key" : "idle_timeout.timeout_seconds", "Value" : "60" } ], "Name" : "simplechat-alb", "Scheme" : "internet-facing", "SecurityGroups" : [ { "Ref": "LoadBalancerSecurityGroup" } ], "Subnets" : [ {"Ref": "subnetPub1"}, {"Ref": "subnetPub2"} ], "Tags" : [ {"Key": "Name", "Value": "simplechat-alb" } ] } }, "Cloud9Env": { "Type": "AWS::Cloud9::EnvironmentEC2", "Properties": { "Name": "simplechat_cloud9_env", "Description": "simplechat_cloud9_env", "AutomaticStopTimeMinutes": "1440", "InstanceType": "t2.micro", "SubnetId": { "Ref": "subnetPub1" } } } } }2.Dockerイメージを登録する
2-1.Amazon ECR にリポジトリを作成する
適当なリポジトリ名で、リポジトリを作成する。(設定はデフォルト)
2-2.Amazon ECR にDockerイメージを登録する
【「1.CloudFormation で環境を準備する#」】で、cloud9でsimplechat_cloud9_env が作成されているので、「Open IDE」を選択し、次のとおりappを展開する。
wget https://ecs-for-aws-summit-online.workshop.aws/simplechat_app.tar.gz tar zxvf simplechat_app.tar.gz cd simplechat_ecs_app/Amazon ECRから「プッシュコマンドの表示」をクリックし、後は手順どおり、ログイン→ビルド→タグ付け→プッシュする。
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin .dkr.ecr.us-east-1.amazonaws.com docker build -t simplechat . docker tag simplechat:latest .dkr.ecr.us-east-1.amazonaws.com/simplechat:latest docker push .dkr.ecr.us-east-1.amazonaws.com/simplechat:latest3.Dockerコンテナの作成
3-1.クラスターの作成
「AWS Fargate」を指定。(他の設定はデフォルト)
3-2.タスク定義
イメージは先程作成したAmazon ECRのリポジトリのURIを指定する。ポートマッピングは80にする。
環境変数を設定する。
キー バリュー DB_HOST RDSインスタンスのURI DB_USER 【1.CloudFormation で環境を準備する】で指定したもの DB_PASS 【1.CloudFormation で環境を準備する】で指定したもの 3-3.サービス
デプロイメントはローリングアップデート
4.アプリケーションの確認と修正
ALBのDNS名にアクセスして、アプリケーションを色々触ってみる。
そのあと、Cloud9を開き、アプリケーションの適当な箇所を修正し、「File」から「Save」。その内容が反映されるか確認する。
【2-2.Amazon ECR にDockerイメージを登録する】の手順と同様にログイン→ビルド→タグ付け→プッシュする。
※実際はAmazon ECRのリポジトリにおいて「タグのイミュータビリティ」を「有効にする」に設定し、イメージ更新毎に一意のタグを付けるようにする。
※「タグのイミュータビリティ」→ 有効にすると同じタグを上書きができなくなる。今回は、ECSのサービスで「新しいデプロイの強制」のチェックボックスをオンにだけ変更し、更新する。
タスクは2つになるはずですがしばらくすると、1つになります。(ローリングアップデート)
最後にalbのDNSにアクセスし、変更が反映されたか確認する。
- 投稿日:2020-09-18T10:25:57+09:00
AWS SAA合格体験記
AWSの合格体験記
たくさんありますよね。
何番煎じかわかりませんが、
これから受ける人の役に立てれば
いいと思っています。
AWS SAAとは
- AWS Solutions Architect -Associateの略
- 主にAWSを構築する人向け
- 運用者向けはSysOpsAdministrator
- 開発者向けはDeveloper
なぜSAAを取ろうと思った
- AWSの知識をちゃんと身に着けたい
- EC2やS3,VPCといった基本的なサービスを学ぶので、範囲も広く体系的に学べそう
- 内外的にAWSを知っている人という保証が欲しかった
勉強期間
- 3ヶ月強ぐらい(結構長い)
- 平日の毎朝毎晩と土曜日(日曜日は休みたかった)
勉強方法
次のudemyの教材を中心に勉強
書籍は参考書として活用
使った教材
udemy
- これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座(SAA-C02試験対応版)
- 【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集(6回分390問)
問題に関しては3回ぐらい解いて90%ぐらいまで正答率を上げた
書籍
※2018年に試験がupdateしているので古すぎるものは注意
感想(勉強)
- AWSの知識はもちろんインフラそのものの知識がなかったのでそこから学べた
- udemyのハンズオンを行ったので実際の経験としても身についた(NATゲートウェイを削除し忘れて高額な請求が来たことも思い出)
- とって終わりではなく、活かしていかないともったいない(本当にそう)
感想(試験)
- 個々のサービスは分かっていてもまず、問題文で何を求められているか理解するのに時間がかかった
- udemyの問題集ほど細かいところは聞かれなかった印象
- 受験料15,000円はちょっと高い
- 投稿日:2020-09-18T10:11:00+09:00
AWS QuickSight ~ demo
2つのCSVファイルをjoinする
必要項目を入力します。”Enable autodiscovery of…”にチェックすることを忘れない。
「ファイルのアップロード」から、CSVファイルをSPICE領域にアップロードする。
特定の列を基準にJOINするため、「データを追加」よりもう一つのcsvファイルをアップロードする。
2つの円のようなアイコンを選択し、JOINする列を指定し、結合タイプはInnerを指定する。
※InnerはONで指定した条件が、結合する両方のテーブルにマッチするレコードのみを返します。
これで2つのCSVファイルが、結合されました。
データタイプを変更する
自動的にInt(整数)型で認識されているものを、String型(文字列)に変更する。
視覚化
「保存して視覚化」後、SPICEに取り込んだデータを可視化していきます。
左からフィールドをDrag & Dropすることでそのフィールドのデータをもとに可視化が行われます。
ML(機械学習)インサイトの機能
与えられたデータから予測値をだすことができます。「予測を追加」から行えます。
ドリルダウン
X軸に3つの項目(A B C)、Y軸に1つの合計の値があったとします。
「ドリルダウン」を利用すると、AのBの値というように視覚化することが可能になります。
コントロールとフィルタ
フィルタするためのコントロールを作成し、その作成したコントロールでフィルタを作成していきます。
例えば●月●日〜●月●日までの合計や平均とか。作成すると、続いてパラメータの接続先を選択するダイアログが出るので、「コントロール」を選択します。
これで開始日と終了日のコントロールが作成できたので、「フイルタ」を次の条件で作成していく。
後は好きにフイルタの日付を変更して、グラフが変わるか確認して見るだけ。
- 投稿日:2020-09-18T09:06:09+09:00
AWSの関連記事まとめ
自分用のまとめです。
構築
- 冴えないAWS環境の育てかた α
https://dev.classmethod.jp/articles/saenai-aws-1/- AWS システム構築 非機能要件ヒアリングシートを公開してみた
https://dev.classmethod.jp/articles/survey-non-functional-requirement/
最適化
- AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ
https://qiita.com/tmknom/items/303db2d1d928db720888- Well-Architected Toolを試してみた
https://qiita.com/kc_n/items/4b6e84e3b1113e4e37e5- AWS Well-Architected フレームワークおよび AWS Well-Architected ツールが更新されたので、どこが変わったのかを調べてみた
https://dev.classmethod.jp/articles/updates-aws-well-architected-framework-tool/- AWS再入門 AWS Trusted Advisor編
https://dev.classmethod.jp/articles/cm-advent-calendar-2015-getting-started-again-aws-td/
セキュリティ
- 【レポート】AWS Security Hubを用いたセキュリティとコンプライアンス対応 – Deep Dive into AWS Security Hub – #AWSSummit
https://dev.classmethod.jp/articles/aws-summit-online-2020-track4-1315-1345-security-hub/- Security Hub 自動修復のソリューションを Organizations 組織全体に展開してみる
https://dev.classmethod.jp/articles/security-hub-auto-remediation-in-organization/- 10分でできる最低限のIAM設定見直し
https://dev.classmethod.jp/articles/iam-revirew-10min/- AWS セキュリティ
https://qiita.com/leomaro7/items/604db3c021233ac2eaf0- [神ツール]セキュリティインシデントの調査が捗るAmazon DetectiveがGAしたのでメリットとオススメの使い方を紹介します https://dev.classmethod.jp/articles/how-to-detective/
- GuardDuty で S3 への不審なアクティビティを脅威検出できるようになりました!
https://dev.classmethod.jp/articles/guardduty-threat-detection-coverage-to-s3/- AWS提供のマネージドルールでDevelopersIOへの攻撃を検出してみた
https://dev.classmethod.jp/articles/aws-waf-devio-202009/
コスト削減
- AWSのリザーブドインスタンス(RI)とは?Amazon EC2での料金事例やSavings Plansとの比較も紹介
https://cloudnavi.nhn-techorus.com/archives/1738- コスト最適化の決定版!AWS Cost Explorerの推奨事項にAWS Compute Optimizerが統合されました
https://dev.classmethod.jp/articles/aws-cost-explorer-rightsizing-recommendations-integrates-with-aws-compute-optimizer/- Savings Plansの何がすごいのか。リザーブドインスタンスとの違いは?
https://qiita.com/hayao_k/items/650a2131a96c8f20cb97- 本文は長いけどわかりやすい(はず)AWSコスト削減の要 -RIとSPパーフェクトマスター 2020-
https://dev.classmethod.jp/articles/riandsp2020/- パート1. AWSタグ付けストラテジー入門
https://itnews.org/news_contents/aws-tagging-best-practices- [レポート]コスト管理を再考する #AWSSummit
https://dev.classmethod.jp/articles/aws-summit-online-2020-day1-track4-1530-1600/- ナビタイムジャパンの AWS コスト最適化の秘訣~Amazon EC2 フリート有効活用およびコスト最適化手法~
https://dev.classmethod.jp/articles/aws-summit-online-2020-cus-62/
バックアップ
- AWS Backup によるバックアップ取得の全体像をやっぱり絵に描いて理解してみた https://dev.classmethod.jp/articles/aws-backup-perfect-understand/
便利ツール
- CloudMapperを使ってAWS環境を可視化する
https://qiita.com/kooohei/items/58b6d8654a89c911a2e9
HowTo
- HowTo [AWS Start-up ゼミ / DevDay 編] よくある課題を一気に解説! 御社の技術レベルがアップする 2018 秋期講習 https://www.slideshare.net/AmazonWebServicesJapan/aws-startup-devday-2018
CI/CD
- AWS Code DeployでEC2にデプロイする
https://nonsensej.xyz/articles/2019/02/28/aws-code-deploy
⇒githubでの許可はこれ
https://docs.aws.amazon.com/codedeploy/latest/userguide/integrations-partners-github.html#behaviors-interactions-organization-managed- CircleCIからAWS Code Deployを実行する
https://nonsensej.xyz/articles/2019/03/04/aws-code-deploy-circleci- 【レポート】 AWS の継続的インテグレーション/継続的デリバリー総まとめ!モダンアプリケーション構築のための CI/CD ベストプラクティス! #AWSSummit
https://dev.classmethod.jp/articles/202009-report-aws-summit-2020-aws-26/
- 投稿日:2020-09-18T08:26:26+09:00
[AWS] マネジメントコンソールのLambdaの管理画面からStep Functionsのワークフローを確認できるようになりました
Launch
9/17に、「AWS Lambda adds console support for visualizing AWS Step Functions workflows」ということで、LambdaのコンソールでStep Functionsのワークフローのビジュアライズ機能がLaunchされました。
Lambdaの管理画面
メニュー蘭に「Step Functions state machines」の項目があります。
Step Functions state machinesのメニューを選択すると、上部にStep Functionsの使い所のようなものが説明されていて、その下にState machineの一覧があります。
今回は、「[AWS] Step Functionsで遊んでみる(SAM + Lambda) Part.3(分岐編)」のものをDeoloyしてあります。
State machineのリンクを選択すると、そのステートマシンのいつものグラフが表示されます。
そして、その下に、ステートマシンから呼び出しているLambdaが一覧表示されます。
今回はシンプルな例なので1つしかないですが、このステートマシンで使用しているLambdaと、どのStepで使用しているかが一目でわかるようになりました。
まとめ
これまで、Step Functionsの管理画面から、ARNを確認しながら追う必要がありましたが、その必要がなくなりました。
ステートマシンで複数のLambda関数を呼び出しているケースでは、Lambda間の相関がわかりやすくなったのではないでしょうか。
- 投稿日:2020-09-18T02:34:48+09:00
【AWS】CloudFrontのBehaviorsを使った分岐でハマったところ
とりあえずメモレベルで残す
装飾とかまとめはまた別途書きます。
やりたかったこと
Route53に登録したホストゾーンのドメインに対して、URLから判定してS3かAPIGatewayに飛ばす
- Default (*)の場合はS3(Staticページ)に飛ばす
/api/*
の場合はAPIGatewayに飛ばすハマったところ
- APIGatewayのStageが
dev
を設定- CloudFrontの
Origins
に設定したAPIGatewayの設定のOrigin Path
に/dev
を設定CloudFront
のBehaviors
のPath Pattern
には/api/*
されていた<cloud front path>/api/*
でAPI叩いたら"message": "Missing Authentication Token"
が返ってきた原因
- 上記の設定だと、APIGatewayの
/api/dev/
Stageにアクセスしようとするため、リソースがないと言われる
- CloudFrontの
Behaviors
のPath Pattern
に設定する値と、APIGatewayのStageが一致している必要がある- CloudFrontの
Origins
に設定したAPIGatewayの設定のOrigin Path
の値は設定しない対応
- APIGatewayのStageに
api
を追加- CloudFrontの
Behaviors
のPath Pattern
に/api/*
を設定- CloudFrontの
Origins
のOrigin Path
の設定値はなし参照ページ
“Missing Authentication Token” — CloudFront/APIG Troubleshooting
- 投稿日:2020-09-18T01:15:14+09:00
AWS Route53 親ドメインを移行しないでEC2にサブドメイン設定
やりたいこと
一つドメインを持ってるのですが、それは別なサイトに使ってるので、サブドメインでやりたいなーとおもった
前提
EIPと紐付いているEC2がある
EC2はnginx導入済み下記記事の続き
https://qiita.com/ntm718/items/f896c8e4fb801777954bドメイン取得済み
ちなみにお名前ドットコム(DNS設定するだけなのでどこでも良いですが)1.サブドメインのRoute 53ホストゾーンを作成します。
ホストゾーンの作成を選択
注意
ホストゾーン1つにつき、0.50 USD/月発生します(50円ほど)ドメイン名につけたいサブドメインを含むドメイン名を入力
test
部分がサブドメイン
パブリックホストゾーンのまま、作成作成するとネームサーバーが振られます
このNS値を、現在の親ドメインのDNSレコードに追加しますDNS設定
登録している親ドメインのDNS設定できるページに行きます
自分の場合、お名前ドットコムなので下記のような画面ですそして、レコードに
- サブドメイン
- Type: NS
- TTL: 900 (キャッシュ時間なので増やしても良い)で入力し、
VALUEに、Route53の手順で作成された、タイプNS
のns
から始まる値を入力します
NSは4レコードなのでVALUEだけ4レコードを追加しますお名前ドットコムの場合DNSレコード設定用ネームサーバー変更確認を選択せず、設定まで行き完了です
EC2と紐付け
AWS Route53の作成したホストゾーンにレコードを追加します
レコード作成を選択シンプルルーティングで次へ
シンプルなレコードを定義を選択し、
- レコード名: 空欄
- 値/トラフィックのルーティング先: レコードタイプに応じた~~
- 値: EIPのパブリックIPv4
- レコードタイプ: A作成後、サブドメインホストゾーンに戻り、レコードをテストするを選択
レスポンス取得を押し、EIPのパブリックIPが返却されたらOK
nginx設定
server_nameの設定する
EC2にssh接続し
sudo vi /etc/nginx/nginx.conf
server_name
の箇所を、サブドメイン含むドメインを入力再起動して、反映させる
sudo systemctl restart nginx確認
ブラウザでドメイン入力、表示されたら成功
https
ではなくhttp
で確認しましょう(SSLがまだの場合)感想
netlifyでブログをサブドメインで運用しており、そのときにドメインのDNSを移しているのに気づかずハマり、SSLしてないからhttpなのに、httpsにして少し溶かしてしまいましたが、簡単な構成だと楽にできますね