複数 AWS アカウントで起動中のリソース一覧作りたい時によく利用しています。
1 |
|
EC2 インスタンス名の一覧を取得したい意図です。
1 | aws ec2 describe-instances --query 'Reservations[*].Instances[*].Tags[?Key == `Name`].Value' --output text |
以上
参考になれば幸いです。
Python3 でファイルの中身をロードする方法をまとめた備忘録です。
1 | cat <<EOF> sample.txt |
1 | with open("sample.txt", "r") as file: |
1 | greeting: |
1 | with open("sample.txt", "r") as file: |
1 | greeting: |
1 | with open("sample.txt", "r") as file: |
1 | ['greeting:\n', ' ja: こんにちは\n', ' en: hello\n', '\n', 'sports:\n', ' ja: 相撲\n', ' en: バスケット\n'] |
1 | pip install pyyaml |
1 | import yaml |
1 | {'greeting': {'ja': 'こんにちは', 'en': 'hello'}, 'sports': {'ja': '相撲', 'en': 'バスケット'}} |
以上
参考になれば幸いです。
terraform provider の更新等、 dependabot で Pull Request の作成をしていると
自分がアサインされていないので気づきにくいです。
その為、定期的に見ておく必要があります。
ですが、管理するリポジトリが多いと全て見に行くのは手間なのでまとめてスクリプトで見れる様にします。
事前に gh コマンドで認証を済ませておく
1 | gh auth login |
1 | #!/bin/zsh |
console 実行結果
1 | Showing 1 of 1 pull request in kenzo0107/xxx-terraform that matches your search |
ある程度数える程度だったので対応する terraform プロジェクトは配列で持たせましたが、
そこも動的にしたい場合は terraform プロジェクトとわかるファイルがあるリポジトリを抽出してもよいと思います。
以上
参考になれば幸いです。
terraform はバージョンアップ頻度が高く、
プロジェクトによってバージョン差分が生じるので
複数バージョンを管理できると運用がスムーズです。
terraform だけバージョン管理するのであれば tfenv がメジャーです。
ですが、 tflint, tfsec も導入を推奨しているので
あらゆるライブラリのバージョン管理が同じ方式でできるので
asdf を推してます。
参考: https://asdf-vm.com/guide/getting-started.html
1 | brew install asdf |
1 | asdf plugin add terraform |
1 | cd path/to/terraform-project |
.tool-versions が生成され、以下のようにバージョン管理されます。
1 | terraform 1.5.0 |
.tool-versions が指定されていると
そのディレクトリ配下ではインストールされていればそのバージョンを利用する様になります。
1 | $ asdf plugin add tflint |
ローカルで tflint, tfsec のバージョンアップによる挙動の変化を試したい場合に利用しています。
以上
参考になれば幸いです。
SAM プロジェクトで管理する API Gateway について
AWS Config rule: api-gw-execution-logging-enabled
に対応すべく、
アクセスログを有効化した際にハマった話です。
Events.*.Type = Api
で作成した API Gateway では SAM 上でアクセスログ有効化の設定ができません。
どのようにしたら API Gateway のアクセスログ有効化できるか調査しました。
1 | Resources: |
2023-07-07 時点、
API Gateway を新たに作成しそちらに乗り換えるしか方法がありません。
その場合、カスタムドメインでない限り、API Gateway のドメインは変更されます。
Type: AWS::Serverless::Api
等、別途 API Gateway 作成し、RestApiId
で参照することで
アクセスログや X-Ray Tracing の有効化が可能でした。
1 | Resources: |
もしドメイン変更を許容しない場合は、コンソール上でアクセスログを有効化することは可能です。
sam deploy 後も上記処理について変更がないことを確認済みです。
AWS::Serverless::Api で定義し API Gateway をインポートしようとすると以下エラー発生
1 | ResourceTypes [AWS::Serverless::Api] are not supported for Import |
AWS::ApiGateway::RestApi で定義し API Gateway をインポートしようとすると以下エラー発生
1 | You have modified resources [ServerlessRestApi, ServerlessRestApiDeployment2ababeb14f, ServerlessRestApiProdStage, FunctionMessagePermissionProd] in your template that are not being imported. Update, create or delete operations cannot be executed during import operations. |
他リソースの設定が不足しているようだ。
AWS::ApiGateway::Stage のみインポートしようとすると以下エラー発生
1 | abcd1a2b3c|Prod already exists in stack arn:aws:cloudformation:ap-northeast-1:123456789012:stack/Bot-Stack/e50458c0-1234-12ab-a12f-123a4b5c6d7e |
以上
参考になれば幸いです。
以前は CloudWatch LogGroup をインポートしましたが
今回は IAM Role をインポートの設定例です。
基本手順は CloudWatch LogGroup と同様ですが、
異なる部分だけ記載します。
1 | ... |
API Gateway のアクセスログ管理用ロググループへログを配信する IAM Role をインポートします。
1 | [ |
import.json にインポート対象のリソースを追加し
先程の template.yml と同じディレクトリに保存します。
1 | aws cloudformation create-change-set \ |
capabilities は CAPABILITY_NAMED_IAM にする必要があります。
IAM Role リソースに独自の命名をしたい場合に利用します。
あとは同様に手順を進めます。
以上
参考になれば幸いです。
既にデプロイ済みの SAM プロジェクトは CloudFormation に Stack が作成されています。
その Template
タグで template の内容をローカル環境で template.yml
で保存しましょう。
保存先はどこでも良いです。
1 | ... |
今回は API Gateway のアクセスログ管理用ロググループをインポートします。DeletionPolicy: Retain
としているのは、リソースを作成せず、Stack にインポートする為です。
1 | [ |
import.json にインポート対象のリソースを追加し
先程の template.yml と同じディレクトリに保存します。
1 | $ aws cloudformation create-change-set \ |
※ このコマンド実行した時点ではインポートは実行されません。
コマンド実行後、以下のように Change sets
にセットが追加されていれば OK です。
Change sets の Name がリンクになっているのでクリックします。
右上の Execute change set
ボタンをクリックし Stack へのインポート処理を実行します。
ステータス= IMPORT_COMPLETE
でインポート完了となります。
Stack にインポートしたリソースに Stack で管理されている旨のタグが追加されていることが確認できます。
インポート用に用意した template.yml とは異なるデプロイ時に参照する yml ファイルにインポートしたリソースを定義します。
ここでは DeletionPolicy: Retain
は不要です。
1 | Resources: |
SAM プロジェクトで管理するテンプレートファイルで DeletionPolicy: Retain
の差分がある為、変更の差分が出ます。
1 | $ sam deploy -t ${TEMPLATE_FILE} \ |
デプロイ後、再度デプロイしようとすると差分がなくなることを確認できました。
1 | $ sam deploy -t ${TEMPLATE_FILE} \ |
これにてインポートが問題なくできたことを確認できました。
Stack > Template を template.yml で保存し、対象リソースを削除し以下コマンドを実行します。
インポートしたロググループを除外する Change set を作成します。
1 | aws cloudformation create-change-set \ |
コンソール上で Execute change set を実行し削除できます。
以上
参考になれば幸いです。
1 | $ pip3 install xxx |
一時的に tmp ディレクトリを指定してからインストールを再度実行することで回避してみます。
1 | $ mkdir $HOME/tmp |
これでうまくいきました ♪
以上
参考になれば幸いです。
AWS Savings Plans Coverage API 実行時に DataUnavailableException エラーが発生しました。
1 | aws ce get-savings-plans-coverage --time-period Start=2023-05-31,End=2023-06-01 --group-by Type=DIMENSION,Key=INSTANCE_TYPE_FAMILY Type=DIMENSION,Key=REGION Type=DIMENSION,Key=SERVICE |
発生する条件を AWS サポートに確認しました。
「対象期間について Savings Plans 適用対象サービスを使用していない場合、上記エラーが発生する」
とのこと。
Cost Explorer で Savings Plans > Coverage report にも以下メッセージがありました。
No savings plans coverage data was returned for this time period. Please adjust the time period or filters if this seems incorrect.」
Savings Plans カバレッジ取得時に DataUnavailableException エラーが発生する
= Savings Plans 適用対象サービスを使用していない
= Savings Plans を買う必要がない
ということでした。
以上
参考になれば幸いです。
1 | cat /etc/os-release |
1 | sudo apt-get install -y libffi-dev libssl-dev |
1 | Could not install packages due to an EnvironmentError: [Errno 28] デバイスに空き領域がありません |
一時的に tmp ディレクトリを指定してからインストールを再度実行することで回避できます。
1 | $ mkdir $HOME/tmp |
それでも以下エラーが出ました。
1 | $ pip3 install grpcio google-cloud-speech |
デフォルトの pip でなく
python3 で https://bootstrap.pypa.io/get-pip.py 実行し
pip をインストールし直し、再チャレンジしてみます。
1 | wget https://bootstrap.pypa.io/get-pip.py |
以上で成功しました。
参考になれば幸いです。
]]>Raspberry Pi と OpenAI を通じて英会話しよう!という動機から
最初の一歩として USB スピーカーから指定したテキストを読み上げる様にしてみました。
Marstudy Raspberry Pi 4 Model B Starter キット で
プリインストールされた Raspbian OS を利用しています。
1 | $ cat /etc/os-release |
サンワサプライ コンパクト PC スピーカー MS-P08UBK を利用します。
自分が購入した 2023-05-10 は ¥857 でした。
1 | aplay -l |
1 | // plughw:<カード>,<デバイス> |
1 | pip3 install pygame |
1 | curl https://www.soundjay.com/buttons/button-3.mp3 -o button.mp3 |
1 | import pygame |
以下実行し mp3 が再生されることが確認できます。
1 | python3 play_sound.py |
1 | pip3 install gTTS |
1 | from gtts import gTTS |
以下実行しスピーカーから「はい、お元気ですか?」と再生されます。
1 | $ python3 speech.py |
以上
参考になれば幸いです。
次回はマイクから音声認識させる設定を執筆したいと思います。
]]>alpine イメージで awscli をインストールする際の備忘録です。
1 | RUN apk add --no-cache \ |
alpine イメージをベースで RUN curl
が失敗し以下エラーが出力されました。
1 | curl: (48) An unknown option was passed in to libcurl |
curl と libcurl のバージョンの不一致が原因で
curl-dev をインストールすることで解決しました。
1 | FROM alpine |
以上
参考になれば幸いです。
パブリックアクセスのブロックが無効となっている S3 Bucket で
パブリックアクセスのブロックを有効化しその後、無効化した際に
Object の ACL に影響があるか確認します。
公式ドキュメントに記載がある通りであることが確認できた。
ACL = public-read の S3 Object が
パブリックアクセスブロックを有効化するとパブリックアクセスが不可となり
その後、パブリックアクセスブロックを無効化するとパブリックアクセス可能となることが確認できた。
AWS コンソール上だとパブリックアクセスブロック有効化時に
Everyone Read の権限が消えるので一瞬ドキッとするが、
無効化した際に元に戻ることが確認できた。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/access-control-block-public-access.html
ブロックパブリックアクセス設定は既存のポリシーまたは ACL を変更しません。そのため、ブロックパブリックアクセス設定を削除しても、パブリックポリシーまたは ACL を持つバケットまたはオブジェクトは再びパブリックにアクセス可能になります。
パブリックアクセスのブロックを有効化し、その後、無効にしてもオブジェクトの ACL には影響がない、
とのこと。
1 | resource "aws_s3_bucket" "test" { |
1 | $ echo "public read" > public_read.txt |
acl = public-read とした場合誰でもアクセスできる公開状態であることを確認できる。
1 | // acl = public-read にしているので S3 Object URL にアクセスできる |
1 | resource "aws_s3_bucket_public_access_block" "test" { |
パブリックアクセスブロックが有効化されたことを確認
public_read.txt の Everyone の Read が消えている
private.txt は特に変わらず
public_read.txt, private.txt いずれもアクセスを試みるも 403 Forbidden となることを確認
1 | $ curl -I https://test-by-kenzo-tanaka.s3.ap-northeast-1.amazonaws.com/public_read.txt |
再度パブリックアクセスブロックを無効化する
1 | resource "aws_s3_bucket_public_access_block" "test" { |
パブリックアクセスのブロックが無効化されたことを確認
public_read.txt の Everyone の Read が復活していることを確認
private.txt は変わらず
public_read.txt はパブリックアクセスが可能となり
private.txt はパブリックアクセスが不可であることが確認できました。
1 | $ curl -I https://test-by-kenzo-tanaka.s3.ap-northeast-1.amazonaws.com/public_read.txt |
結論に記載した通り、公式ドキュメントの通りであることが確認できました。
以上
参考になれば幸いです。
terraform の linter として tflint を導入し、
GitHub Actions でチェックが良かったのでまとめます。
asdf で複数バージョンの導入・切り替えが可能です。
asdf 経由で導入
1 | asdf plugin-add tflint https://github.com/skyzyx/asdf-tflint |
Pull Request 作成・更新時に tflint を走らせる設定です。
以下ディレクトリ毎に tflint を実行しています。
1 | name: Lint |
おおよそ完了する時間は 1 分も掛からないですが、3 分もあれば終わるのと
意図せぬ長時間の実行を回避すべく、3 分でタイムアウトする様に設定しています。
リソース数にもよるので適宜設定してください。
いらなそう?と思いましたが、公式に以下コメントがあります。
When you install plugins with tflint –init, TFLint calls the GitHub API to get release metadata. By default, this is an unauthenticated request, subject to a rate limit of 60 requests per hour per IP address.
認証されていないリクエストで、IP アドレスあたり 1 時間あたり 60 リクエストというレート制限がある為、
それを回避する為に設定する必要があるとのこと。
以上
参考になれば幸いです。
RDS PostgreSQL のバージョンアップ時にハマったことをまとめておきます。
RDS PostgreSQL のバージョンアップ時に以下エラーが発生しました。
1 | │ Error: updating RDS DB Instance (stg-media-postgresql-10): operation error RDS: ModifyDBInstance, https response error StatusCode: 400, RequestID: 15badd67-ea50-4189-9542-deb2df162e05, api error InvalidParameterCombination: RDS does not support creating a DB instance with the following combination: DBInstanceClass=db.t2.micro, Engine=postgres, EngineVersion=14.6, LicenseModel=postgresql-license. For supported combinations of instance class and database engine version, see the documentation. |
db.t2.micro の場合、 postgresql 14.6 の作成をサポートしていない、
とのこと。
これは terraform で
db.t2.micro を db.t3.micro へ
postgresql を 10.23 を 14.6 へと
同時に変更しようとしても発生します。
DB インスタンスクラスでサポートされている DB エンジン
db.t2 は PostgreSQL は 13 より前がサポート対象でした。
Choosing a major version upgrade for PostgreSQL
10.23 は 14.6 へのバージョンアップが可能であることが確認できた。
上記手順に従って実施します。
準備済みのトランザクション - アップグレードを実行する前に、すべての準備済みのトランザクションをコミットまたはロールバックします。
次のクエリを使用して、開いている準備済みのトランザクションがインスタンスにないことを確認します。
1 | SELECT count(*) FROM pg_catalog.pg_prepared_xacts; |
Reg* データ型 - アップグレードの実施前に reg* データ型の使用をすべて削除します。regtype と regclass を除き、reg* データ型をアップグレードすることはできません。このデータ型は、Amazon RDS でのアップグレードで使用されているため、pg_upgrade ユーティリティで維持することはできません。
1 | SELECT count(*) FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n, pg_catalog.pg_attribute a |
対象 DB では上記特段検出されず問題ないことを確認できました。
1 と 2 を同時実行はできず、冒頭のエラー文が表示されます。
terraform でも AWS コンソール上でも同様のエラー文です。
1 を実行後、2 を実行する必要がありました。
全体的には上記手順で進めました。
リハーサルで全体のメンテ時間と作業内容の再確認をしておくと
本番でテンパらずにいけるかなと。
以上
参考になれば幸いです。
RDS で突如として対応必須のメンテナンスが現れた時にメンテ延期した方法をまとめました。
突如として 2 日後
に自動適用される DB エンジンバージョンアップのメンテナンスが現れました。
通常であれば AWS からの 1 ヶ月以上前に事前の通知メールがあり、余裕を持って対応できたいたのですが、あまりに突然で回避方法を AWS SA さんやサポートに問い合わせました。
メンテナンスウィンドウを変更することで延期することができました。
元々の Apply date
が 2023-02-19 04:30
です。
2023年2月17日 金曜日
とすると
次回メンテナンスウィンドウを現在日より前の 木曜日
に変更します。
terraform では以下のような修正です。
1 | - maintenance_window = "sat:19:30-thu:20:00" |
すると Apply date
が 2023年2月24日 木曜日
に変更されました。
aws rds describe-pending-maintenance-actions
を実施した所、AutoAppliedAfterDate
や CurrentApplyDate
が無事更新されており、ForceApplyDate
もなかったことから
無事メンテが延期されたことを確認しました。
SA さんに念の為、確認した所、問題なさそうとのことでした。
上記参考に実施しようとしたところ、 Action のメニューに「アップグレードを延期」(Defer upgrade) はありませんでした。
※ 英語版のドキュメントでもなかったです。
これについての AWS SA さんの回答は以下の通りでした。
ちょっと私も自分の環境で再現ができておらず、ドキュメントも見つけられていないのですが、適用できるケースとできないケースがあるのかも知れません。
すでにスタートした Upgrade は延期できない、とは明記されているのですが(明確なお答えができずすみません)
今回の件では適用できないケースだったのかもしれません。
AWS の回答としては以下の通りです。
パッチの緊急性ほか、複数の要素によって、余裕を持って通知されるケースもあれば、事前通知がない状態で突然スケジュールされるケースもある
社内でも確認しましたが、あいにく ○ 日前までに通知する、といった明確な SLA はない
もしメンテナンスのメール通知だけ信じていたら危うく意図せぬサービスダウンが発生していた所でした。
EventBridge でメンテイベントの検知 →Chatbot の仕組みは手っ取り早いと思います。
参考: EC2 等のメンテナンススケジュールを AWS Chatbot で Slack に通知する
私自身はメンテイベントの詳細が把握しづらいので Lambda で整形してから Slack 通知する様にしています。
Lambda は日次で実行し、メンテイベントが消えるまで通知し続ける様にしています。
以上
参考になれば幸いです。
AWS で CloudFront + ECS で Web サービスを配信していますが、
Bot が多く、その対策を WAF で実行しようとしたい際にいくつかつまづきましたので、その備忘録になります。
以下 2 点を試しました。
JP (日本) 以外をブロックしました。
1 | resource "aws_wafv2_web_acl" "main" { |
すると、日本からアクセスしたにも関わらず、
日本外と判断され、ブロックされてしまった事象がありました。
その際はスマートフォン (docomo, au, softbank) でのアクセスでした。
誤検知があったのでこの方法は回避しました。
AWS Bot Control で bot 対策をしてみました。
こちらで現状特段大きな問題がないのですが、
AWS Bot Control を terraform で有効化しようとした際につまづいた点をまとめます。
※2022-11-29 時点でサポートしておらず、 InspectionLevel の設定ができません。
https://github.com/hashicorp/terraform-provider-aws/issues/23290
1 | { |
※ 2022-11-29 時点
Bot Control Rules の設定をサポートしていないので、手動で設定等が必要です。
以下設定を rule {}
ブロック内に設定すれば、検知モード (ブロック等せずカウントだけ実施する) にできます。
1 | override_action { |
先述した issue で既に言及されているのでいずれサポートされると思います。
利用時には要注意です。
https://github.com/hashicorp/terraform-provider-aws/issues/23287
意図しない挙動があるとも否定できないので terraform で完結させたい。
shell スクリプトのテストや構文チェック等をするのも憚れる。
rate limit やその他 SQLi, XSS を設定していたとしても
Bot が一時的に複数 IP 元からリクエストがあると防ぐことが難しいです。
GEO 制限で抑えられたら良かったのですが、リクエストの多いサービスの場合でご検知があると
それだけで商用環境での利用は憚れます。
Bot Control で検知モード (Count) で様子を見て、適宜ブロック設定をしていくのが安全でした。
以上
参考になれば幸いです。
1 | let dt = new Date('2022-10-31T15:00:00+0900'); |
答えは 2022-10-01T06:00:00.000Z
です。
10 月 31 日の 1 ヶ月前は 9 月 31 日、
9 月は 30 日までなのでその翌日の 10 月 1 日になってしまったというものです。
先月の 1 日を取得する場合は先に setDate(1)
が必要です。
1 | let dt = new Date('2022-10-31T15:00:00+0900'); |
ちなみに先月の月末は setDate(0)
することで取得できます。
1 | let dt = new Date('2022-10-31T15:00:00+0900'); |
Lambda で 10 月 31 日の本日に 1 ヶ月前が取得できないな?となってちょっとハマってしまった問題でした。
terraform で簡易的な Lambda スクリプトを管理しており、極力 package を利用せずに nodejs で日付計算したかった背景があります。
以上
参考になれば幸いです。