20210121のAWSに関する記事は16件です。

AWS EC2 AMIを利用して構築したRedash9.0(beta)でCloudWatch Logs Insightsのデータを取得する

What's this?

Redash9.0(beta)でデータソースとしてCloudWatch Logs Insightsが新規追加されたので、Redash9.0の構築からデータ取得までの手順をまとめた記事です。

Redashとは

Redashは、(主に)SQLの分析結果をわかりやすく可視化し共有するオープンソースBIツールです。
「RDS」「Redshift」「BigQuery」「Google Spreadsheet」など50種類以上の様々なデータソースと連携が可能で、複数のデータソースのデータを結合させることも可能です。

Redash9.0で追加されたデータソース

New Data Sources: Amazon Cloudwatch, Amazon CloudWatch Logs Insights, Azure Kusto, Exasol.

Redash公式のchange logを見るとまだbeta版ですが、9.0から下記データソースが新規で追加されています。

  • Amazon Cloudwatch
  • Amazon CloudWatch Logs Insights
  • Azure Kusto
  • Exasol

構築手順

前提

  • ローカル環境はmacOS + iTerm2
  • AWSアカウントは既に作成済
  • CloudWatch Logsにデータが存在している

【手順1】Redash8.0セットアップ

EC2インスタンス作成

Docker on EC2のAMIがRedashの公式から提供されているので、こちらを利用します。

今回は東京リージョンでのインスタンス作成をしたいので、「ap-northeast-1」を選択

image.png

次にインスタンスタイプを選択します。

Launch the instance with the pre-baked AMI we create (for small deployments t2.small should be enough):

Redash公式ページでは小規模の開発環境であればt2.smallで十分とありましたが、9.0については、t2.smallではメモリが不十分で上手く動作しなかったため、t2.mediumを選択しました。
どちらのインスタンスタイプも無料枠ではないので注意してください。

image.png

インスタンスタイプを選択したら、「確認と作成」ボタンを押します。

インスタンス起動前に下記画面が表示されるので、キーペアを作成していない場合は、
任意のキーペア名をつけてキーペアの作成をします。
このとき発行されるキーペアはインスタンスにSSH接続する際に必要になるため安全な場所に保存しておきます。

image.png

これでインスタンスの作成は完了です。
今回利用したAMIにインストールされているRedashのバージョンは8.0になるので、後ほど9.0へのバージョンアップを行います。

セキュリティグループの作成

次にセキュリティグループの作成をします。
下記ポートをインバウンドルールに追加します。

  • SSH接続のための22番ポート
  • HTTP接続のための80ポート
  • HTTPS接続のための443ポート

image.png

この際、検証用に利用する方は自宅や職場など特定のIPアドレスのみを許可する設定にしておいた方が安全です。

セキュリティグループの作成が完了したら、先ほど作成したEC2インスタンスとの関連付けを行います。

インスタンス一覧画面に戻り、セキュリティグループを変更します。

image.png

作成したセキュリティグループを選択し保存します。
もし余分なセキュリティグループがインスタンスに関連付けされている場合は削除します。
これでセキュリティグループの関連付けは完了です。

Elastic IPの作成

今回検証用に有料のインスタンスタイプを利用しているため、利用しない時はインスタンスを停止し費用を抑えたいです。
EC2にデフォルトで付与されるパブリックIPアドレスは停止、再起動の度に変わってしまうため固定IPアドレスを設定します。

Elastic IPの新規作成をします。

image.png

作成したElastic IPをEC2インスタンスに関連付けます。

image.png

これで固定IPの作成とインスタンスへの関連付けの完了です。

この時点でブラウザに発行されたElasticIPアドレスでアクセスするとRedashの管理画面が表示されるはずです。

EC2インスタンスへSSH接続確認

作成したインスタンスにSSH接続できるか確認します。
ここからはローカル環境での作業となります。

<Home Directory>/.ssh/configに下記を追記します。
<ホスト名>,<Elastic IP>,<キーペアファイルのパス>は適宜各自の環境に置き換えてください。

Host <ホスト名>
 HostName <Elastic IP>
 User ubuntu
 Port 22
 UserKnownHostsFile /dev/null
 StrictHostKeyChecking no
 PasswordAuthentication no
 IdentityFile <キーペアファイルのパス>
 IdentitiesOnly yes

コマンドラインツールからssh <ホスト名>でサーバ接続できればOKです。

【手順2】Redash9.0へのバージョンアップ

Redash8.0→9.0へのバージョンアップを行います。

ssh <ホスト名>でRedashサーバに接続

  • コンテナの起動確認
# redashディレクトリに移動
cd /opt/redash/
# コンテナの起動確認
sudo docker-compose ps

          Name                         Command               State              Ports
------------------------------------------------------------------------------------------------
redash_adhoc_worker_1       /app/bin/docker-entrypoint ...   Up      5000/tcp
redash_nginx_1              nginx -g daemon off;             Up      443/tcp, 0.0.0.0:80->80/tcp
redash_postgres_1           docker-entrypoint.sh postgres    Up      5432/tcp
redash_redis_1              docker-entrypoint.sh redis ...   Up      6379/tcp
redash_scheduled_worker_1   /app/bin/docker-entrypoint ...   Up      5000/tcp
redash_scheduler_1          /app/bin/docker-entrypoint ...   Up      5000/tcp
redash_server_1             /app/bin/docker-entrypoint ...   Up      0.0.0.0:5000->5000/tcp
redash_worker_1             /app/bin/docker-entrypoint ...   Up      5000/tcp
  • コンテナの停止
sudo docker-compose down
  • docker-compose.ymlの変更

redash/CHANGELOG.mdのUpgradingを参考に下記を変更します。

  • imageをredash/redash:8.0.0.b32245→redash/redash:previewに変更
  • services/schedulerのenvironmentを削除
  • services 配下にworkerを追加
sudo vi docker-compose.yml

修正後のdocker-compose.yml

version: "2"
x-redash-service: &redash-service
  #最新のimageに変更
  image: redash/redash:preview
  depends_on:
    - postgres
    - redis
  env_file: /opt/redash/env
  restart: always
services:
  #workerを追加
  worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "periodic emails default"
      WORKERS_COUNT: 1
  server:
    <<: *redash-service
    command: server
    ports:
      - "5000:5000"
    environment:
      REDASH_WEB_WORKERS: 4
  scheduler:
    <<: *redash-service
    command: scheduler
    #schedulerのenvironment を削除
  scheduled_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "scheduled_queries,schemas"
      WORKERS_COUNT: 1
  adhoc_worker:
    <<: *redash-service
    command: worker
    environment:
      QUEUES: "queries"
      WORKERS_COUNT: 2
  redis:
    image: redis:5.0-alpine
    restart: always
  postgres:
    image: postgres:9.6-alpine
    env_file: /opt/redash/env
    volumes:
      - /opt/redash/postgres-data:/var/lib/postgresql/data
    restart: always
  nginx:
    image: redash/nginx:latest
    ports:
      - "80:80"
    depends_on:
      - server
    links:
      - server:redash
    restart: always
  • コンテナのビルド
docker-compose up --force-recreate --build
  • Redashにログインしversion9.0になっていることを確認

画面左下のユーザー名をクリックするとRedashの現在のバージョンが表示されます。
9.0.0-betaになっていればバージョンアップ完了です。

image.png

【手順3】CloudWatch Logs Insightsデータの取得

最後に作成したRedashでCloudWatch Logs Insightsのデータ取得を行います。

IAMでRedashユーザーの作成

RedashからAWSリソースにアクセスするためにIAMにRedashユーザーを作成します。

AWS IAMから ユーザー > [ユーザーを追加]

image.png

プログラムによるアクセスにチェックを付けます

image.png

アクセス権限から既存のポリシーをアタッチを選択します。
今回はLambdaのCloudWatch Logs Insightsデータを取得したいためAWSLambdaFullAccessにチェックを入れます。

image.png

ユーザーの作成が完了すると、アクセスキーが発行されるためダウンロードし安全な場所に保管します。

image.png

データソースの追加

Setting > Data Sources > [New Data Data Source] からAmazon CloudWatch Logs Insightsを選択します。

image.png

データソース追加に必要な情報を設定します。

  • Name:任意
  • AWS Region:東京リージョンなら「ap-northeast-1」
  • AWS Access Key:IAMで発行したもの
  • AWS Secret Key:IAMで発行したもの

Create後、[Test Connection]が成功すればデータソースの追加完了です。

image.png

指定のロググループのデータを取得

最後です。
Queriesからデータ取得のクエリを作成します。
左上のプルダウンから先ほど追加したデータソースを選択

記法についてはCloud Watch Logs Insightsの記法と変わりません。
今回はTwitter APIのログデータを取得しました。

無事取得できました。

{
    logGroupName: '/aws/lambda/rep_Tweet',
    startTime: 1590926139,
    queryString: '
        fields @timestamp,@message |
        filter @message like /event/ |
        sort @timestamp desc |
        display @timestamp,follow_events.0.target.name,follow_events.0.type,follow_events.0.target.screen_name,follow_events.0.target.description |
        limit 1
    '
}

image.png

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

sdk-goでdynamoDBの複雑なstructの値をupdateする

やりたいこと

GoでのdynamoDBに対しての操作は割とめんどかったりします。単純なStringやIntのものであればまだ良いのですが、ListのMapのなかのListとか、値の構造が複雑になってくると気が滅入ります。

// シンプルなパターン
&dynamodb.UpdateItemInput{
  TableName: aws.String("sampleTable"),
  Key: // 省略,
  ExpressionAttributeValues: map[string]*dynamodb.Attribute{
   ":ssv": {
      S: aws.String("sampleStringValue")
    },
   ":siv": {
      N: aws.String(strconv.Itoa(0)) // ここもintをstringに型変換してそれをaws.String()してkeyにはNを指定って感じでわかりづらい。
    },
  },
  UpdateExpression: aws.String("set sampleStringValue=:ssv and sampleIntValue=:siv")
}

// 複雑なパターン
&dynamodb.UpdateItemInput{
  TableName: aws.String("sampleTable"),
  Key: //省略,
  ExpressionAttributeValues: map[string]*dynamodb.Attribute{
    ":slv": {
      L: [
       {
         M: {
           ":smp": {
            aws.String("sample")
            }....
         }
       }
      ]
    },
  }
}

これを楽にやれるのがsdk-goのexpressionってやつです。

expressionの使い方

update := expression.UpdateBuilder{}.Set(
  expression.Name("sampleComplexValue"),
  expression.Value(sampleCompexValue)
)

expr, err := expression.NewBuilder().WithUpdate(update).Build()

&dynamodb.UpdateItemInput{
  TableName: aws.String("sampleTable"),
  Key: //省略,
  ExpressionAttributeNames: expr.Names(),
  ExpressionAttributeValues: expr.Values(),
  UpdateExpression: expr.Update()
}

上の例よりかなりスマートにかけますね。可読性も格段に上がります。
expression.Valuesの引数に複雑な(もちろん単純なものでもなんの問題もありませんが)値を渡すだけで、ここまでできるのは結構ありがたい。

もちろんexpressionは上記の例のような更新処理だけでなく、Query処理等にも使えるので積極的に使っていきたいところですね。

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

AWS 認定 デベロッパー – アソシエイト(DVA-C01)取得するまでにやったこと

dva-c01.png

はじめに

DX 技術本部の yu-yama です。
AWS 認定 デベロッパー – アソシエイトを取得したので取得までの流れを記します。

受験前の AWS 経験

AWS 経験は 4, 5 年で、コアサービスは一通り触っており、ソリューションアーキテクトアソシエイトを 2020 年 6 月に取得しています。

AWS 認定ソリューションアーキテクトアソシエイト(SAA-C02)取得するまでにやったこと

学習期間

  • 7 カ月間薄く(だらだらと)
  • 試験直前の 1 週間は毎日少しでもと決めて DVA 関連のテキストに目を通すようにしていました

学習方法

  1. 試験ガイドを参照し、試験範囲を確認する

  2. 合格記を読み、試験のイメージをつかむ

  3. AWS 認定 – 試験準備ワークショップ 「デベロッパー - アソシエイト」を受ける

    などが分かります。ここのアーキテクチャ設計の原則は超重要なので暗記しましょう

  4. ブラックベルトを読む

  5. AWS 認定デベロッパー アソシエイト模擬試験問題集(5 回分 325 問) | Udemy

    • 1周目は終了後、正解・不正解関わらず解説も全部読み、理解が浅すぎると思ったサービスについてはブラックベルトも読みました。
    • 2周目は終了後、不正解のみのチェックを行いました。
    • 試験結果推移

      • 演習テスト1: 1 周目は 24%でした...
      • 演習テスト2: 1 周目は 33%でした...
      • 演習テスト1: 2 周目は 56%でした...
      • 演習テスト2: 2 周目は 75%でした...

      思ったより点数が上がらないのと、この問題集は難易度が高いというのを他で見かけたので 演習テスト2までを2周した時点で1度試験を受けてみることにしました。

模擬試験

  • 受けませんでした。Udemy の模擬試験を実施していれば問題文のボリュームも解答の選択肢の雰囲気も同じなので不要だと思います。

試験を受けた感想と試験のコツ

  • 時間にはかなり余裕があります。全問解いた時点で1時間程度余っていました。
  • SAA の時と同様に、確信をもって正解を選択できないが、消去法で残ったものを選択して進めました。 試験終了ボタンを押下してアンケート回答後にすぐに結果が表示されるので試験終了ボタンを押すときは緊張感あります...
  • 問題の難易度ですが、AWS 認定デベロッパー アソシエイト模擬試験問題集(5 回分 325 問) | Udemyの問題と比べると少しだけUdemyの方が難しいという印象です。試験準備ワークショップとブラックベルトだけではちょっと足りないかもしれないので、演習テストを受けないにしても解答解説全斜め読みくらいはしておくと良いかも。

試験のコツ

  • まずは一通り解きましょう。迷いがあるものは後で見直しにチェックを付けて最後に一気に見直せます。
  • 正解が分からない場合、原則に従い正解を選択する。

    • 今回はこれが功を奏した気がしています。DVA の原則は Exam Readiness: AWS Certified Developer – Associate (Digital) (Japanese) | AWS トレーニングと認定で教えてもらえます
    • 今回特に役立った原則は以下になります。

      • スケールアップよりもスケールアウト
      • アクセスキーより IAM ロールが望ましい
      • アンマネージドサービスよりもマネージド
      • リソースや API を直接公開する事は避け、AWS エッジサービスや API ゲートウェイを使用する
      • サーバーにセッション状態を保存していては優れたアーキテクチャにはならない
      • インフラストラクチャを疎結合化する
      • サーバーレス化する
      • トラブルシューティング時には、セキュリティグループや NACL を常に確認する
      • VPC のプライベートサブネット内に作成されたインスタンスは、NAT を使用しない限りインターネットと通信することが出来ない
      • インターネットと通信するには、インターネットゲートウェイとルートテーブルのルートが必要
      • EBS ボリュームは、EC2 インスタンスに疎結合されている。
        • ブートボリュームの場合を除いて、アタッチまたはデタッチできる

      ユースケースに対する最適なアーキテクチャを問われる問題が出た場合、各々の単語の意味は分からなくても、原則に従った解答を選択しておけば良い結果に近づける筈。

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

CloudWatchAlarmの動作確認をしてみる

目的

わが社ではCloudWatchAlarmを設定し、アラート内容をタスクとしてチケット化するシステムを作っているのですが、「アラート内容をタスクとしてチケット化」の部分を確認したいので、CLIで無理やりアラートを発報させる方法を調査しました。備忘録です。

手順

CloudWatchの権限を持ったユーザでCloudShellからCLIをたたくだけ。

cat << EOF > ALARM.json
{
    "AlarmName": "【Alarm名】",
    "StateValue": "ALARM",
    "StateReason": "Test Alarm"
}
EOF
aws cloudwatch set-alarm-state --cli-input-json file://./ALARM.json
rm -f ./ALARM.json

今回はファイルインプットを採用。
ファイルインプットのほうが、設定内容の可視性を上げやすいのでよさげですね。

以上。

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

[Alibaba Cloud] オンプレミスからVM移行ができるServer Migration Center 触ってみた

この記事の目的

Alibaba CloudのマイグレーションツールがServerMigrationCenterとして新たにリリースされていたので軽く触ってみました。
CentOSのサーバーのイメージコピーして、Alibaba Cloud環境に移してみます。

ServerMigrationCenterの概要

  • Alibaba Cloudのマネージドサービスの1つ
  • オンプレミスクラウド環境から複数サーバーをAlibaba Cloud環境に移行するために利用するツール
  • 増分移行をサポートしているので、サーバーを停止する必要なく移行が可能
  • 複数タスクを同時実行可能(利用シチュエーションは不明)
  • ソースディスクのパーティションスキーマを取得してディスクパーティションも複製可※この際にディスクサイズを指定可

image.png

その他の特徴

  • 増分データ同期

    • サーバー停止をする必要がない.
    • ソースサーバーの増分データをAlibabaCloudに同期する.
  • コンテナレジストリへのデータ移行

    • サーバーをContainerRegistryに移行可能.
  • マルチスレッドデータ送信

    • マルチスレッドデータ送信をサポート.
    • 高帯域幅が利用可能な場合に帯域幅の使用量と伝送効率が向上
  • 移行タスクのステータス監視が可能

    • 監視ができるのでエラーを早期に特定しトラブルシューティングが迅速に.

ローカル作業

## マイグレーションツールDL後、対象のディレクトリに移動. 
## llでファイルを確認. 
## 今回はLinux_x86*64bitのエージェントを利用します. 
root@tnoce:~/dev-main/Alibaba_Cloud_Migration_Tool$ ll
total 58968
drwx------@  7 SHU  staff      224 Jan 21 13:22 ./
drwxr-xr-x  25 SHU  staff      800 Jan 21 13:23 ../
-rwxr-xr-x@  1 SHU  staff    21010 Jan 12 15:39 Release Note.txt*
-rwxr-xr-x@  1 SHU  staff  6111564 Jan 18 20:04 go2aliyun_client2.5.2_linux_i386.zip*
-rwxr-xr-x@  1 SHU  staff  6044981 Jan 18 20:04 go2aliyun_client2.5.2_linux_x86_64.zip*
-rwxr-xr-x@  1 SHU  staff  8727685 Jan 12 15:39 go2aliyun_client2.5.2_windows_i386.zip*
-rwxr-xr-x@  1 SHU  staff  9277052 Jan 12 15:39 go2aliyun_client2.5.2_windows_x86_64.zip*

## SFTPで対象マイグレサーバーにログイン
$ sftp -oIdentityFile=`YOUR KEY-PAIR` root@[IPアドレス]

## sftp put -r でマイグレツールのディレクトリをまるごとサーバー側にアップロード.
> sftp put -r /dev-main/Alibaba_Cloud_Migration_Tool/go2aliyun_client2.5.2_linux_x86_64.zip*

サーバー作業

## sshでログイン.
## llでsftpでputされたディレクトリが存在するか状態確認
[root@eigo-split go2aliyun_client2.5.2_linux_x86_64]# ll
total 5208
drwxr-xr-x 3 root root    4096 Jan  8 17:32 Check
-rw-r--r-- 1 root root    6357 Jan  6 17:51 client_data
-rw-r--r-- 1 root root   20169 Jan  6 17:51 EULA
drwxr-xr-x 2 root root    4096 Jan  6 17:55 Excludes
-rwxr-xr-x 1 root root 5289072 Jan 18 19:56 go2aliyun_client
-rw-r--r-- 1 root root     100 Jan 21 12:31 user_config.json

## vimでACK, ACK-Sを編集
[root@eigo-split go2aliyun_client2.5.2_linux_x86_64]# vim user_config.json
{
        "access_id" : "YOUR ACK-ID INPUT HERE",
        "secret_key" : "YOUR ACK-SECRET-KEY INPUT HERE"
}

## chmodでアプリケーションに実行権限を付与
[root@eigo-split go2aliyun_client2.5.2_linux_x86_64]# chmod +x go2aliyun_client

## ./go2aliyun_clientでアプリケーションの実行
[root@eigo-split go2aliyun_client2.5.2_linux_x86_64]# ./go2aliyun_client
[2021-01-21 12:34:23] [Info]  ========= Goto Aliyun Client 2.5.2. =========
[2021-01-21 12:34:24] [Info]  =========   Run In Daemon Mode   =========
[2021-01-21 12:34:24] [Info]  Goto Aliyun Begin...
[2021-01-21 12:34:24] [Info]  Load User Config...
[2021-01-21 12:34:24] [Info]  Load Client Data...
[2021-01-21 12:34:24] [Info]  Check System Info [CentOS x86_64]...
OS Info: CentOS Linux 7 (Core) (3.10.0-1062.18.1.el7.x86_64)
CPU Info: Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz
CPU Usage: 2 Cores (1.01%) Memory Usage: 1.81GB/4.00GB (45.25%)
Hostname: eigo-split IP Address: 10.68.30.177 Mac Address: 00163E004478
[2021-01-21 12:34:25] [Info]  Verify User Account...
You Have Not Created ServiceLinkedRole For SMC:
When you import source server for the first time, a service linked role is automatically created for you to use relevant features.
Role Name: AliyunServiceRoleForSMC
Role Policy: AliyunServiceRolePolicyForSMC
Role Description: By default, SMC assumes this role to access your resources in other Alibaba Cloud services, such as ECS, VPC, and RAM.
Documentation: https://help.aliyun.com/document_detail/122993.html
Do You Want To Created It and Continue? (yes/no): yes
[2021-01-21 12:34:29] [Info]  Generate SSH Key...
[2021-01-21 12:34:29] [Info]  Import Source Server...
[2021-01-21 12:34:31] [Info]  Import Source Server [s-bp13vdcjxh8tg0y9eyj4] Successfully!
[2021-01-21 12:34:32] [Info]  Check Source Server Status...
[2021-01-21 12:34:33] [Info]  Check Replication Job Status...
Please Goto SMC Console To Create New Job, time: 2m30s    \

Alibaba Cloud作業

  • SMCコンソールで移行ソースが作成されているのを確認
  • 移行タスクの作成に進む
    image.png

  • 基本セッティング

    • Target Region:イメージをコピーするターゲットリージョン
    • Task name:移行タスクの名前
    • Description:移行タスクの説明
    • Target Disk Size (GiB):ターゲットのディスクサイズ
    • Resource Type:ECSイメージかコンテナイメージ
    • Image Name:イメージの名前
    • 许可证类型:ICPの取得

image.png

  • タグ&ネットワーク(オプション)
    • Migration Task Tag:タグ付け(任意)
    • Network Type:Public Network OR VPC ⇒ VPCは閉域接続かVPN接続が必要
  • アドバンス設定(オプション)
    • Transmission speed limit (KB/S):
    • Compression Level:コンプレッションレベルを上げると伝送効率は上がるが、CPU負荷が上がる
    • Checksum:チェックサム機能(*ファイルデータの整合性を高めますが、移行速度は落ちる)

image.png

  • 移行タスクを作成すると以下のようにpreparingの状態になりますので、気長に待ちます.
    image.png
    image.png

  • タスクが完了したようです。
    image.png

  • Imageができました。
    image.png

イメージからECSの作成

  • CreateInstanceから作成
  • いつもどおりECSの購入を進めていく image.png

イメージから作成したインスタンス

問題なく同一のディレクトリ構造を持ったVMが作成されました
image.png

まとめ

マイグレーションに時間はかかりましたが、シンプルでわかりやすく使えました。
あとは、速度を速めたい場合はオプション値の設定も有効かなと。
イントラ経由でVMイメージの移行もできるようなので、VPCモードを試してみる価値はありそうです。

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

sam local start-apiでヘッダーが勝手にキャメルケースになるんだが?

表題の通り、sam local start-apiでヘッダーが勝手にキャメルケースになる問題についてです。

こちらにドンピシャの回答があるのですが、内部で使っているFlaskの仕様だそうです。
Headers are received in Camel-Case · Issue #1860 · aws/aws-sam-cli

仕方ないのでNode.jsでは下記ワークアラウンドをしてヘッダーをすべて小文字にして対応しましょう。
(Pythonならissueのコメントにサンプルコードが載っています)

const toLowerCaseKey = function(object) {
    let newObject = {};
    for (let key in object) {
        if (object.hasOwnProperty(key)) {
            newObject[key.toLocaleLowerCase()] = object[key];
        }
    }
    return newObject
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【フロントエンド開発】初投稿

初めに

フロントエンドでチーム開発をしています。
チーム開発でのあれこれや、プロジェクトで使用している技術関連の話題を投稿していきます。

使用している技術関連

  • React
  • javascript/CSS/HTML
  • typescript
  • Electron
  • ASP
  • Git
  • AWS
  • GraphQL
  • Node.js
  • ReactNative/expo

目的

開発中に躓き調査した内容や、新しい技術を取り入れた場合に苦労したことなどを
個人のナレッジにとどめず共有していくことを目的としています。

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

AWSのRDSを削除したのに課金され続けてしまった話。。。原因が分かった。。。

AWSのRDSを使いアプリを作成していましたが、
結構月額が高いし、あまり使わなくなったので
RDSを削除しました。

ですが、なぜが、まだ課金されている???

スクリーンショット 2021-01-21 11.10.51.png

なぜ?????

結論:スナップショットが残っていると課金し続けるようです。。。

https://ap-northeast-1.console.aws.amazon.com/rds/home?region=ap-northeast-1#snapshots-list:

スナップショットが残っている人は削除しましょう!!!!!!

やはり
AWSは奥が深いですね。。。

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

CloudFormationでApiGatewayのログを有効化に必要な諸々の設定をする

共通の設定が必要なのでどっかに書く

Resources:
  APIGatewayPushToCloudWatchLogsRole:
    Type: AWS::IAM::Role
    Properties:
      Description: "Allows API Gateway to push logs to CloudWatch Logs."
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          Effect: Allow
          Principal:
            Service: apigateway.amazonaws.com
          Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs

  ApiGatewayAccount:
    Type: AWS::ApiGateway::Account
    Properties:
      CloudWatchRoleArn: !GetAtt APIGatewayPushToCloudWatchLogsRole.Arn
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsアプリをAWSにデプロイするまでにすごく苦労したので教訓メモ

何コレ

ポートフォリオを作成する上で以下の環境構築を行っていたが、個人的にとても苦労したので備忘録として残しておきたいと思い書いた。

設定環境

AWS EC2(1年間無料で使えるインスタンス)
AWS RDS
Ruby 3.0.0
Rails 6.1.1
puma 5.1.1
mysql 5.7

アプリはまだRails newしただけの状態

使った教材

こちらの記事を参考に環境構築を行った。わからない単語などは都度調べながら。
https://qiita.com/take18k_tech/items/5710ad9d00ea4c13ce36
記事自体はタイトルの通り、知識としては今は無くとも環境構築できるのではと思う(インフラ大事だからいずれはもっと学習するつもり)。

何が苦労したのか

主に以下の点でとても苦労した。

・記事とおりやっているが、capistranoの設定あたりから壮大につまずく
→これは記事が悪いわけでは無く(それ以外はすんなり設定できたので非常に感謝している!)、環境というのはどうしても個々で異なるので、あまり鵜呑みにせず、できたらラッキーぐらいの心持ちで参照した方が良かったなと思った。
具体的な箇所は後述。

・エラー解決しようと検索するも英語記事ばかり
→当然といえば当然なのかもしれない。日本語記事無いかな〜と甘えたことばかり考えていた。
解決策は英語記事(特にgithubのissue)に載っていることが多かったと思う。初学者ありがちだと思うが、本当に英語に慣れないといけないなと。

具体的につまずいた箇所①

・デプロイ先のサーバーにリポジトリをpushできない
→少し前にRails newしたアプリなら、マスターブランチ名がmasterかもしれない。
しかし最近デフォルトのブランチ名がmastermainになってしまった為、このままではpushできないという話。
https://capistranorb.com/documentation/getting-started/configuration/
こちらを参考に英語と戦いながら設定を変更すればうまくいく!

具体的につまずいた箇所②

・デプロイしてみたら--daemonが無効だと怒られる
→エラー内容そのままですが、デーモンプロセスが無効と表記されている。

daemon無効エラーログ
05:38 puma:start
      using conf file /var/www/hogehoge/shared/puma.rb
      01 $HOME/.rbenv/bin/rbenv exec bundle exec puma -C /var/www/shikaku_sns/shared/puma.rb --daemon
      01 bundler: failed to load command: puma (/var/www/hogehoge/shared/bundle/ruby/3.0.0/bin/puma)
      01 /var/www/hogehoge/shared/bundle/ruby/3.0.0/gems/puma-5.1.1/lib/puma/cli.rb:50:in `initialize'
      01 :
      01 invalid option: --daemon
      01  (
      01 OptionParser::InvalidOption
      01 )
      01
長いので割愛。hogehogeはアプリ名

なるほどわからん、となりコミュニティで質問したところ、こちらを紹介いただく。
https://github.com/seuros/capistrano-puma#systemd
ここらを見ることで解決の糸口を見つけることができた!
(今思うと、コミュニティにいらっしゃる強者エンジニアの方はほとんどgithub(一次ソース)を真っ先にみていることがわかった。)

具体的につまずいた箇所③

・Capistranoを使ったデプロイができない!
→参考記事の中では、
capistrano3-pumaのバージョン5にpumaを再起動できないバグが出ている
とあります。確かにrestartすると以下のようなエラーが表示。

restartエラーログ
01:03 puma:restart
      01 sudo /bin/systemctl restart puma
      01 Failed to restart puma.service: Unit is not loaded properly: Invalid argument.
      01 See system logs and 'systemctl status puma.service' for details.
以下長いので割愛

マジかーと思い、途方にくれていたが、このままではイカンと思いコミュニティで恐る恐る質問。
このエラーは以下の記事で無事解決!
https://qiita.com/AQeNku/items/81ddae388d8615125a24

今回得られた教訓

(1)エラーをきちんと読む
エラーが出たわかんね〜、で済ませない。
この記事が自分にはとても有効。質問する際はこちらを念頭に質問する。
https://qiita.com/rhiroe/items/4349b9f412364aa2c729

(2)エラー内容を見て、まずは一次ソースを検索する
自分がつまずいた箇所は何もGithubのusageに詳しく載っていたりしたので。それ以外にも例えばAWSに関するエラーだったらAWSの公式ドキュメントを見る。そこを見て何言ってんだこいつ?みたいになってしまったらQiitaなどの記事を見るのは悪くなさそう。

(3)質問して返ってくることをあまり期待しない
メンタサービスなどを利用している場合は別だが、無料のコミュニティで質問をしても絶対に返ってくる保証は無い。
世の中の人たちそんなに暇では無い。基本的には自分で考えては検証し、また考えては検証の繰り返しを行うマインドセットを持っていないと多分この先もダメ。

まだまだ先は長いのでドンドン進む

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

AndroidからAWS Cognitoのユーザプールをさっくり使う

スクリーンショット 2021-01-21 8.25.15.png

サインアップやサインイン、パスワード再発行など、ユーザ管理がないアプリケーションを見かけない日はありません
とはいえ自前でバックエンドのシステムを作るのも大変...
でもAmplifyはちょっとリッチすぎる気がする...

そんな私のための備忘録です

下記のことができます

  • メールアドレス、パスワードによるサインアップ、ログアウト
  • メールアドレス認証
  • パスワード再発行

メールアドレスやパスワードはガッツリ個人情報です
その辺りの管理をAWSにお願いできるのはかなり気楽ですよねー

前準備

SES (Simple Email Service)に配信用のメールアドレスを登録する

0_SESにメールアドレスを登録し、送られたURLをクリックしてVerifyする.PNG

AWSのSESに、認証コードを送信する用のメールアドレスを登録、認証しておきます
登録したメールアドレスに確認用のURLが届くのでクリックすると認証できます
Verification Statusが"verified"になっていれば使用可能です

1_登録したメールアドレスでテストメールを送信する.PNG

"Send a Test Email"ボタンで自分自身にテストメールを送り、無事受信できればOKです

Cognitoにユーザプールを作成する

2_CognitoUserPoolを作成する.PNG

AWS Cognitoのダッシュボードにアクセスし、UserPoolを作成します
送信元のEメールアドレスに、先ほど認証したメールアドレスを登録し、Amazon SESによるEメール配信を”はい”に指定します

3_アプリクライアントの認証はとりあえずこんな漢字.PNG

アプリクライアント側の設定はこんな感じです

Androidクライアントを実装する

依存関係

依存関係に、下記を追加します

build.gradle
implementation 'com.amazonaws:aws-android-sdk-cognitoidentityprovider:2.19.0'

いよいよ実装

初期化

val userPoolId = "ap-northeast-1_xxxxxxxx"
val clientId = "yyyyyyyyyyyyy"
val clientSecret = "zzzzzzzzzzzzzz"
val userPool = CognitoUserPool(context, userPoolId, clientId, clientSecret, Regions.AP_NORTHEAST_1)

先ほど作成したCognitoUserPoolのUserPoolId, ClientId, ClientSecretを使ってインスタンスを作成します
以後、このuserPoolインスタンスを使って各種アクセスをおこないます

サインアップ

サインアップをするには2つのメソッドが必要です

  1. signUpInBackground : userPoolにユーザを作成する
  2. confirmSignUpInBackground : cognitoユーザを認証する

まずはsignUpInBackgroundです
この時点でuserPoolにユーザが追加され、本人確認用コードが送信されます
ただしUNCONFIRMEDの状態で何もできません

fun signUp(username: String, 
           password: String,
           successCallback: () -> Unit, 
           failureCallback: (exception: Exception?) -> Unit
) {
    val userAttributes = CognitoUserAttributes()

    userPool.signUpInBackground(username, password, userAttributes, null,
            object : SignUpHandler {
                override fun onSuccess(user: CognitoUser?, signUpResult: SignUpResult?) {
                    successCallback()
                }

                override fun onFailure(exception: java.lang.Exception?) {
                    failureCallback(exception)
                }

            }
    )
} 

このままだとサインインも何もできないので、続いて本人確認をする必要があります
送信された認証用コードを使ってconfirmSignUpInBackgroundを呼ぶとCONFIRMED状態になります

fun confirmSignUp(username: String, 
                  verifyCode: String,
                  successCallback: () -> Unit,
                  failureCallback: (exception: Exception?) -> Unit
) {
    userPool.getUser(username).confirmSignUpInBackground(verifyCode, false,
        object : GenericHandler {
            override fun onSuccess() {
                successCallback()
            }

            override fun onFailure(exception: Exception?) {
                failureCallback(exception)
            }
        })
}

サインイン

サインインにはgetSessionInBackgroundを使用します
一度サインインに成功すると端末内にセッションとして状態が保持されるようです
今回は2段階認証を有効化していないので、getMFACodeなどはコールされない(はず)

fun signIn(username: String, 
           password: String,
           successCallback: () -> Unit,
           failureCallback: (exception: Exception?) -> Unit
) {
    userPool.getUser(username).getSessionInBackground(
        object : AuthenticationHandler {
            override fun onSuccess(userSession: CognitoUserSession?, newDevice: CognitoDevice?) {
                successCallback()
            }
            override fun getAuthenticationDetails(
                authenticationContinuation: AuthenticationContinuation?,
                userId: String?
            ) {
                val authenticationDetails = AuthenticationDetails(userId, password, null)
                authenticationContinuation!!.setAuthenticationDetails(authenticationDetails)
                authenticationContinuation.continueTask()
            }

            override fun getMFACode(continuation: MultiFactorAuthenticationContinuation?) {
                /* should not be called */
            }

            override fun authenticationChallenge(continuation: ChallengeContinuation?) {
                /* should not be called */
            }

            override fun onFailure(exception: Exception?) {
                failureCallback(exception)
            }
        })
}

パスワード再発行

パスワードの再発行にはforgotPasswordInBackGroundを使います
実行するとパスワード再発行用の認証コードがメールアドレスに送られ、getResetCodeコールバックが返ってきます
その時に一緒に得られるcontinuationを使って、新しい認証コードとパスワードを設定すると完了です

認証周りはサインアップと似たようなものかと思いきや、少し違いますね

fun forgotPassword(username: String,
                   successCallback: () -> Unit,
                   verifyCallback: () -> Unit,
                   failureCallback: (exception: Exception?) -> Unit
) {
    userPool.getUser(username).forgotPasswordInBackground(
        object: ForgotPasswordHandler {
            override fun onSuccess() {
                successCallback()
            }

            override fun getResetCode(forgotPasswordContinuation: ForgotPasswordContinuation?) {
                continuation = forgotPasswordContinuation
                verifyCallback()
            }

            override fun onFailure(exception: Exception?) {
                failureCallback(exception)
            }
        })
}

fun verifyPasswordReset(password: String, verifyCode: String) {
    continuation?.apply {
        setPassword(password)
        setVerificationCode(verifyCode)
        continueTask()
    }
}

まとめ

cognito側の仕様にはあまり触れていませんが、これでさっくり使えます!

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

LaravelアプリをAWSにデプロイする

LaravelアプリをAWSにデプロイする手順をメモ書き程度に残す

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

PythonでS3バケット内の一覧を取得し、特定のKeyで検索 Key名と最終更新日、カウント数をファイルに出力

所用で必要になったので

# -*- coding: utf-8 -*-
import boto3

PUBLIC_S3_BUCKET_NAME_TEST = 'バケット名'

def access_count():
    count = 0
    with open('file.txt', 'w') as f:
        # バケットの一覧取得
        S3 = boto3.resource('s3')
        S3BUCKET = S3.Bucket(PUBLIC_S3_BUCKET_NAME_TEST)

        for obj in S3BUCKET.objects.all():
            if '検索名' in obj.key:
                count += 1
                print(count, obj.key, obj.last_modified, file=f)

        print('total=' + str(count), file=f)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSのControl Towerマスターアカウントからセルフマネージド型StackSetsを展開してみた

構成

 前回、AWSのControl Towerマスターアカウントからサービスマネージド型StackSetsを展開してみたの記事を作成しましたが、いくつかデメリットがあったのでセルフマネージド型StackSetsバージョンとしてこちらの記事を執筆します。
 今回の構成はこちら。

StackSetsSelfService.png

 アカウント払い出し時に、BudgetsとSNSをアカウントに展開した上で払い出します。
 セルフマネージド型StackSetsで、OUではなくアカウント指定でBudgets,SNSを展開します。
 セルフマネージド型StackSetsを使用するには、以下のロールが必要です。

アカウント ロール
管理アカウント AWSCloudFormationStackSetAdministrationRole
各ターゲットアカウント AWSCloudFormationStackSetExecutionRole

 StackSetsの展開先が増える度に、ターゲットアカウントにサインインしてIAMロールを作成するのは面倒なので、各ターゲットアカウントの展開は親アカウントからサービスマネージド型StackSetsで展開します。

StackSets 展開するサービス
サービスマネージド型 IAMロール、ポリシー
セルフマネージド型 Budgets,SNS

 セルフマネージド型のStackSetsを展開するために、事前にサービスマネージド型のStackSetsでIAMロールを展開します。

なぜBudgets等をセフルマネージド型で作成するのか

 冒頭でも述べましたが、サービスマネージド型で展開すると今回の場合ではデメリットの方が大きいと判断したからです。
 なお、サービスマネージド型に一般的な欠陥があると言うわけではありません。あくまで私がしたいことと合わなかっただけです。

 デメリットは二つあり、
   ・無駄なサブスクリプションの確認が生じる
   ・メールアドレス変更時に一から設定をし直す必要がある
ことです。

 構成図の通り、各アカウントのBudgets等はアカウントごとに設定が異なります。
 そのため、サービスマネージド型でターゲットをOUで指定すると、OU内のアカウント全てにデフォルトのメールアドレスをエンドポイントとしたSNSが作成されます。
 また、OU内にアカウントが追加されると自動的にStackSetsを展開する自動デプロイ機能も有効化するので、そのときもデフォルトのメールアドレスをエンドポイントとしたSNSが作成されます。

 SNSが作成されると、SNSサブスクリプションの確認メールが通知先に飛びます。
 リンクをクリックするだけの作業ですが、できればしたくありません。
 デフォルトのメールアドレスは実際の通知先として使わないからです。
 後からアカウントごとに通知先を変更します。
 使用しないサブスクリプションの確認メールをクリックすること自体は意味がありません。
 これが一つ目のデメリットです。

 二つ目のデメリットがセルフサービス型に決めた理由です。
 諸事情によりデフォルトのメールアドレスを更新する場合、ターゲットOU内の全アカウントのSNS通知先が、変更した新しいメールアドレスになるからです。
 当然各アカウントが通知したいメールアドレスは新しいメールアドレスではないので、再度設定を上書きし直す必要があります。
 結構な労力になるので、これを避けるためにセルフサービス型で展開します。

 なお、なぜ実際に通知先として使用しない無駄なデフォルトのメールアドレスを設定していたかと言うと、各アカウントで同じ内容のSNSを作成しないからです。
 StackSetsはOU単位で展開するので、複数アカウントで展開します。
 Aアカウントで実際に通知先として使用するメールアドレスで展開しても、BアカウントやCアカウントでは通知先として使用しないので、BやCにとっては後で変更する無駄な通知先となります。
 どのメールアドレスを使用しても、いずれかのアカウントでは無駄な通知先となるので、自分が使用するメールアドレスをデフォルトのメールアドレスとしていました。

管理者アカウントでIAMロール作成

01.png

 StackSetsがIAMロールを利用するので、信頼関係はCloudFormationに対して行います。

スクリーンショット 2021-01-20 19.09.52.png

 ターゲット先アカウントで作成したIAMロールを引き受けられるポリシーを作成します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": [
                "arn:aws:iam::*:role/AWSCloudFormationStackSetExecutionRole"
            ],
            "Effect": "Allow"
        }
    ]
}

スクリーンショット 2021-01-20 19.10.38.png

 ポリシーに適当な名前をつけます。

スクリーンショット 2021-01-20 19.11.36.png

 作成したポリシーをロールに割り当てます。

スクリーンショット 2021-01-20 19.11.55.png

 ロールの名前を間違えないようにつけます。
 AWSCloudFormationStackSetAdministrationRoleです。
 管理アカウントでIAMロール作成完了です。

ターゲットアカウントでIAMロール作成

スクリーンショット 2021-01-20 19.15.11.png

 ターゲットアカウントで、管理アカウントを信頼するIAMロールを作成します。

スクリーンショット 2021-01-20 19.17.52.png

 ポリシーは最低限のポリシーを作成します。

スクリーンショット 2021-01-20 19.18.18.png

 ポリシーに適当な名前をつけます。

スクリーンショット 2021-01-20 19.18.35.png

 作成したポリシーをロールにアタッチします。
 あとはIAMロールの名前を間違えずに設定しましょう。
 AWSCloudFormationStackSetExecutionRoleです。

セルフマネージド型StackSetsでBudgets,SNS展開

 まず、StackSets用にテンプレートをS3にアップロードします。
 いつもは事前にS3にアップロードしませんが、気まぐれでやってみます。

スクリーンショット 2021-01-20 19.23.43.png

スクリーンショット 2021-01-20 19.22.15.png

スクリーンショット 2021-01-20 19.25.09.png

 S3のアップロード完了しました。
 StackSetsを作成します。

スクリーンショット 2021-01-20 19.26.57.png

スクリーンショット 2021-01-20 19.27.11.png

 取り合えず予算額は100ドルにします。

スクリーンショット 2021-01-20 19.27.22.png

 セルフサービスのアクセス許可から、IAMロールを選択し、実行ロール名はデフォルトのままにします。

スクリーンショット 2021-01-20 19.28.19.png

 先ほどIAMロールを作成したターゲットアカウントを指定します。
 StackSetsでBudgets、SNSを展開しました。
 成功しましたが、ターゲットアカウントで展開されているか確認します。

スクリーンショット 2021-01-20 19.32.02.png

 SNSは作成されているようです。

スクリーンショット 2021-01-20 19.32.15.png

 Budgetsも100ドルで作成されています。
 リソースは無事に展開されていました。

サービスマネージド型StackSetsでIAMロール展開

 ターゲットアカウントでのIAMロール作成は、コンソールではうまく行きました。
 ターゲットアカウントにいちいちサインインして作成するのも面倒です。
 次はIAMロールをStackSetsで展開してみます。
 IAMロールはOU単位で展開しても問題ないので、サービスマネージド型で展開します。
 テンプレートは最後に載せます。

スクリーンショット 2021-01-20 19.58.54.png

 サービスマネージド型を選択する画面のキャプチャを撮るのを忘れていますが、サービスマネージド型を選択しています。

スクリーンショット 2021-01-20 20.00.33.png

 IAMロールの展開が成功しました。
 念のため、ちゃんと作成されているかアカウントを移動してみてみます。

スクリーンショット 2021-01-20 21.23.11.png
スクリーンショット 2021-01-20 21.23.27.png

 ポリシー、信頼関係ともに正常に作成できています。

セルフマネージド型StackSetsでスタックの追加を行い、新アカウントにBudgets,SNSを展開する

スクリーンショット 2021-01-20 21.13.31.png

 ターゲットOUへのIAMロール展開が終了したので、ターゲットOU内のアカウントを指定して、StackSetsでBudgets、SNSを展開します。

スクリーンショット 2021-01-20 21.14.59.png

 上書き指定します。
 写真には載っていませんが、スタックを追加する新しいアカウントのIDを指定して作業をしているので、既存のスタックインスタンスには影響を及ぼしません。
 指定した予算額、メールアドレスになっているか確認します。

スクリーンショット 2021-01-20 21.21.07.png

 予算額は50ドルになっているので合っています。

スクリーンショット 2021-01-20 21.22.11.png

 SNSも作成され、指定したメールアドレスになっています。
 StackSetsで展開したIAMロールと、StackSetsで展開したBudgets等が正常に機能していることが確認できました。

テンプレート

Budgets,SNS
Description: "Basic Budget"

Parameters:
  Amount:
    Type: String
    Default: 100
    Description: Budgeted amount
  email:
    Type: String
    Description: Notification email1 address user

Resources:
  Budget:
    Type: AWS::Budgets::Budget
    Properties:
      Budget:
        BudgetName: test1
        BudgetLimit:
          Amount: !Ref Amount
          Unit: USD
        TimeUnit: MONTHLY
        BudgetType: COST
      NotificationsWithSubscribers:
        - Notification:
            NotificationType: FORECASTED
            ComparisonOperator: GREATER_THAN
            Threshold: 50
            ThresholdType: PERCENTAGE
          Subscribers:
            - Address: !Ref SNS
              SubscriptionType: SNS
        - Notification:
            NotificationType: FORECASTED
            ComparisonOperator: GREATER_THAN
            Threshold: 100
            ThresholdType: PERCENTAGE
          Subscribers:
            - Address: !Ref SNS
              SubscriptionType: SNS
  SNS:
    Type: AWS::SNS::Topic
    Properties: 
      Subscription: 
        - Endpoint: !Ref email
          Protocol: email
      TopicName: StackSetsBudgets1
  SNSPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: MyTopicPolicy
        Version: '2012-10-17'
        Statement:
        - Sid: My-statement-id
          Effect: Allow
          Principal:
            Service: budgets.amazonaws.com
          Action: SNS:Publish
          Resource: !Ref SNS
      Topics:
      - !Ref SNS
IAMロール・ポリシー
AWSTemplateFormatVersion: 2010-09-09
Description: Configure the AWSCloudFormationStackSetExecutionRole to enable use of your account as a target account in AWS CloudFormation StackSets.

Parameters:
  AdministratorAccountId:
    Type: String
    Description: AWS Account Id of the administrator account (the account in which StackSets will be created).
    MaxLength: 12
    MinLength: 12

Resources:
  ExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: AWSCloudFormationStackSetExecutionRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !Ref AdministratorAccountId
            Action:
              - sts:AssumeRole
      Path: /
  ExecuteBudgetsPolicy:
    Type: AWS::IAM::Policy
    Properties: 
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - "cloudformation:*"
              - "budgets:*"
              - "sns:*"
            Resource: "*"
      PolicyName: AWSCloudFormationStackSetExecutionRoleBudgetsPolicy
      Roles: 
        - !Ref ExecutionRole

さいごに

 セルフサービス型StackSets作成が初めてだったので結構身構えていましたが、やってみると思ったより簡単であることがわかりました。
 CloudFormationの中にポリシーを入れることに対して苦手意識を持っていましたが、多少改善されたような気がします。
 セルフサービス型にすることで無駄な確認メールが減り、最初から自分が望む設定のリソースを展開できるので結構嬉しいです。
 ただIAMロールをOU単位でばらまくので、使わないアカウントが出る可能性があるのが残念ですが、これは仕方ないですね(たぶん)。
 権限も最低限にしていますし、親アカウントしか使用できないので大丈夫でしょう。

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

Cloud Runでカスタムドメインの設定方法(Route53編)

Cloud Runでカスタムドメインの設定方法(Route53編)
ドメインはさくらインターネットで取得した

Cloud Run コンソールからカスタムドメインを管理をクリック
custom_domain1.png

今回はベースドメインをtoyscreation.jp サブドメインをweekend-hackathonにする
toyscreation.jpと入力して続行

screencapture-console-cloud-google-run-domains-2021-01-20-23_30_25.png

ドメイン所有の確認、TXTレコードをコピー
custom_domain2.png

AWS Route53 コンソールに移動してTXTレコード作成
custom_domain3.png

設定後、確認を押すと認証完了になる
screencapture-google-webmasters-verification-verification-success-2021-01-20-23_32_52.png

サブドメインにweekend-hackathonを入力し続行
custom_domain4.png

DNSレコードが表示されるのでRoute53 で設定

custom_domain5.png

Route53でA、AAA DNSレコードを設定

custom_domain3.png

20~30分待つと完了しドメインの紐付けが完了
screencapture-console-cloud-google-run-domains-2021-01-21-00_31_13.png

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

【初心者】Amazon Inspector を使ってみる

1.目的

  • セキュリティ関連サービスを一通り復習している。一度も触ったことの無かった Amazon Inspector について、チュートリアルレベルの確認を行い概要を理解する。

2.Amazon Inspector とは(自分の理解)

3.やったこと

  • 評価対象とするインスタンスを作成する。
  • Inspectorで以下を行う。
    • 評価ターゲットの作成: ターゲット(評価対象インスタンス)を指定し、Agentをインストールする。
    • 評価テンプレートの作成: ターゲット及び評価項目の選択を行う。
    • 評価を実行し、結果を確認する。
    • 評価結果に基づきOSの設定修正(脆弱性対応)を行い、再度評価を行い結果が変わることを確認する。

4.構成図

  • 監査対象となるインスタンス(Amazon Linux 2)を1つ作成する。
  • Systems Manager (Agentのインストールに使用)との通信のため、インスタンスにEIPを付与してインターネット通信可能とする。

inspectorの図.png

5. 作業手順

5.1 事前準備

  • 評価対象インスタンス(Amazon Linux 2)をパブリックサブネットに作成し、EIPを付与する。(標準のAMIからそのまま起動する。)
  • Inspectorにおいて、評価対象インスタンスの指定はタグを用いて行うため、インスタンスに「Name:mksamba-inspector-target-instance」のタグを付与しておく。
  • Inspectorの評価対象とするにはインスタンスにAgentをインストールする必要がある。Agentは今回はSystems Manager経由でインストールを行うため、インスタンスに対して、Systems Manager を用いるためのrole「AmazonSSMManagedInstanceCore」を付与しておく。

5.2 Inspector 評価ターゲットの作成

  • 「評価ターゲット」の画面にて、評価対象とするインスタンスをタグにより指定し、「評価ターゲット」を作成する。
  • 今回は先ほど作成したインスタンスだけが評価対象となるように、「Name:mksamba-inspector-target-instance」を指定する。

ins01a.png

  • 「Systems Manager - ノード管理 - Run Command」の画面で、評価対象インスタンスに対し、runコマンド(inspector agent のインストール)が実行されたことを確認する。

ins02a.png

  • 「評価ターゲット - Preview Target」の画面で、AgentのステータスがHealthyであることを確認する。

ins03a.png

5.3 Inspector 評価テンプレートの作成

  • 「評価テンプレート」の画面にて、「評価ターゲット」と「評価項目」の組み合わせをテンプレートとして作成する。
  • 今回は以下のように設定した。
    • 評価ターゲット: 前の手順で作成した評価ターゲットを指定
    • ルールパッケージ: あらかじめ定義された4つのルールパッケージ(評価項目集)のどれを用いるのかを選択する。今回は4つのルールパッケージ全てを選択する。
    • Assessment Schedule: 今回は1回のみ実行とするためチェックは外す。
  • 「作成及び実行」を行い、評価テンプレートの作成及び初回評価実行を行う。

ins04a.png

  • なお、4つのルールパッケージの概要は以下の通り。
ルールパッケージ  内容
CIS Operating System Security Configuration Benchmarks-1.0 CIS (Center for Internet Security) ベンチマークは、システムを安全に構成するための構成基準およびベストプラクティス (Microsoft社によるCISの説明 を参照)
Network Reachability-1.1 外部ネットワーク(VPC外)からのネットワーク到達性
Common Vulnerabilities and Exposures-1.1 CVE(common vulnerabilities and exposures) に基づく評価
Security Best Practices-1.0 ssh経由のrootログイン可否などの、AWSが推奨するベストプラクティス

5.4 結果の確認

  • 「評価の実行」画面で、評価実行結果をダウンロードし、レポートとして見ることができる。
  • 今回の結果は以下の通り。「CIS Operating System Security Configuration Benchmarks-1.0」で97件、「Common Vulnerabilities and Exposures-1.1」で4件、「Network Reachability-1.1」で1件、「Security Best Practices-1.0」で1件検出された。
ルールパッケージ  検出数 内容
CIS Operating System Security Configuration Benchmarks-1.0 97 「/tmp を適切に設定しているか確認せよ」などの細かい指摘が多数。
Network Reachability-1.1 1 「sshが空いてる」という想定内の指摘。SRCPortは絞ってあるので問題なし。
Common Vulnerabilities and Exposures-1.1 4 cloud-initに関して3件、chronyが1件。それぞれバージョンが古いとのこと。
Security Best Practices-1.0 1 rootログインが有効とのこと。

ins05a.png

5.5 設定の修正と再評価

  • 「Common Vulnerabilities and Exposures-1.1」で検出された脆弱性を試しに修正してみることにした。
  • 検出された4件の内容(該当するCVE IDと対象のソフトウェア)は以下の通り。
CVE ID 対象のソフトウェア
CVE-2018-10896 cloudinit-0:19.3-3.amzn2
CVE-2020-14367 chrony-0:3.2-1.amzn2.0.5
CVE-2020-8631 cloudinit-0:19.3-3.amzn2
CVE-2020-8632 cloudinit-0:19.3-3.amzn2
  • 普通に yum update したところ、chronyもcloudinitも新しいバージョンに更新された。
[ec2-user@ip-172-16-0-41 ~]$ sudo yum update
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
amzn2-core                                               | 3.7 kB     00:00
amzn2extra-docker                                        | 3.0 kB     00:00
Resolving Dependencies
--> Running transaction check
---> Package chrony.x86_64 0:3.2-1.amzn2.0.5 will be updated
---> Package chrony.x86_64 0:3.5.1-1.amzn2.0.1 will be an update
--> Processing Dependency: libnettle.so.4()(64bit) for package: chrony-3.5.1-1.amzn2.0.1.x86_64
---> Package cloud-init.noarch 0:19.3-3.amzn2 will be updated
---> Package cloud-init.noarch 0:19.3-4.amzn2 will be an update
  • yum update実施後、再度、同じ評価テンプレートを用いて評価したところ、上記については解消(検出されない)になった。

6.所感

  • 概念としては、昔からある「ホスト型脆弱性スキャナ」という感じで、そんなに抵抗感なく理解することができた。
  • 気軽に実行はできるが、出てきた脆弱性のチェック(本当に対処する必要があるのかの確認)は大変なので、使うにしてもルールパッケージの選択などに注意したいと感じた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む