OpenSearch (Elasticsearch) に CloudFront のアクセスログを連携するための Ingest Pipeline

OpenSearch (Elasticsearch) に CloudFront のアクセスログを連携するために必要な Ingest Pipeline についてのメモ。

Ingest Pipeline とは、Document を POST した時に、その Document を登録する前に加工することができる機能。
渡ってきた CloudFront のアクセスログをちょっと加工して、OpenSearch 上で扱いやすくする。

以下コマンド。

curl -H "Content-Type: application/json" -XPUT 'https://{domain}/_ingest/pipeline/cflog' -d '{
  "processors": [
    {
      "grok": {
        "field": "message",
        "pattern_definitions": {
          "CFDATETIME" : "\\d{4}-\\d{2}-\\d{2}\\t\\d{2}:\\d{2}:\\d{2}"
        },
        "patterns":[ "%{CFDATETIME:timestamp}\t%{NOTSPACE:edge_location}\t%{NOTSPACE:response_bytes}\t%{NOTSPACE:client_ip}\t%{NOTSPACE:http_method}\t%{NOTSPACE:distribution_host}\t%{NOTSPACE:http_path}\t%{NOTSPACE:http_status}\t%{NOTSPACE:http_referer}\t%{NOTSPACE:agent}\t%{NOTSPACE:query_strings}\t%{NOTSPACE:cookies}\t%{NOTSPACE:edge_result_type}\t%{NOTSPACE:edge_request_id}\t%{NOTSPACE:host_header}\t%{NOTSPACE:protocol}\t%{NOTSPACE:request_bytes}\t%{NOTSPACE:response_time:float}\t%{NOTSPACE:x_forwarded_for}\t%{NOTSPACE:tls_protocol}\t%{NOTSPACE:tls_cipher}\t%{NOTSPACE:edge_response_result_type}\t%{NOTSPACE:http_version}\t%{NOTSPACE:fle_status}\t%{NOTSPACE:fle_encrypted_fields}\t%{NOTSPACE:request_port}\t%{NOTSPACE:time_to_first_byte:float}\t%{NOTSPACE:edge_detailed_result_type}\t%{NOTSPACE:content_type}\t%{NOTSPACE:content_length}\t%{NOTSPACE:content_range_start}\t%{NOTSPACE:content_range_end}" ],
        "ignore_missing": true
      }
    },
    {
      "remove": {
        "field": "message"
      }
    },
    {
      "user_agent": {
        "field": "agent",
        "target_field": "user_agent",
        "ignore_failure": true
      }
    },
    {
      "remove": {
        "field": "agent",
        "ignore_failure": true
      }
    },
    {
      "gsub": {
        "field": "timestamp",
        "pattern": "(\\d{4}-\\d{2}-\\d{2})\\t(\\d{2}:\\d{2}:\\d{2})",
        "replacement": "$1T$2Z"
      }
    },
    {
      "date": {
        "field": "timestamp",
        "formats": [
          "date_time_no_millis"
        ]
      }
    }
  ]
}'

Ingest Pipeline は(恐らく)上から評価が行われる。
この設定について上から解説する。

1. grok processor

www.elastic.co

grok とは、定義済みの正規表現を使ってテキスト分割して指定した Field にマッピングするツール。
パターンはこの辺を参考に考えていく。
www.alibabacloud.com

また、CloudFront の標準ログは以下の定義を見ながら、パターンを考える。
docs.aws.amazon.com

grok processor では、最初に渡ってきた message という Field を、 patterns に従って各 Field に分割してマッピングするよう指示。

しかし、定義済みの正規表現の中に該当するものがないこともある。その場合、自分でカスタム正規表現を定義できる。 それが pattern_definitions である。

CloudFront の標準ログでは、日付と時間が別の項目として出力されているので、それを1つの timestamp という Field にマッピングするために CFDATETIME という正規表現を定義している。
それ以外は 面倒くさくて 特にこだわりは無いので、全て NOTSPACE (空白以外の文字列) で解析して各 Field にマッピングしている。

2. remove processor

www.elastic.co

grok processormessage Field を各 Filed に分割した後は不要になるので、 message Field を削除している。

3. user_agent processor

www.elastic.co

user_agent processor は指定した Field が User Agent であると認識させ、その User Agent を解析して更に詳細な Field にマッピングしてくれる。

4. remove processor

user_agent processor 処理後は agent Field そのものは不要になるので削除している。

5. gsub processor

www.elastic.co

grok でマッピングした timestamp に入っている文字列では、日付と時間がタブで区切られていて、そのままだと OpenSearch(Elasticsearch) 側に time field として認識してもらえない。
ISO8601 形式に変換するために、 timestampyyyy-MM-ddTHH:mm:ssZ 形式に変換している。

6. date processor

www.elastic.co

ISO8601 形式に変換した timestamp Field の文字列を date Field として認識させる。

Amazon OpenSearch Service でスナップショットリポジトリを登録する

AWS OpenSearch Service でスナップショットを新規に登録する場合、Kibana の Dev Tools からでは実行できない。
https://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/managedomains-snapshots.html#managedomains-snapshot-register

上記ドキュメントに記載の Python サンプルコードを使って登録することで解決する。

import boto3
import requests
from requests_aws4auth import AWS4Auth

host = '' # domain endpoint with trailing /
region = '' # e.g. us-west-1
service = 'es'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)

# Register repository

path = '_snapshot/my-snapshot-repo-name' # the OpenSearch API endpoint
url = host + path

payload = {
  "type": "s3",
  "settings": {
    "bucket": "s3-bucket-name",
    "region": "us-west-1",
    "role_arn": "arn:aws:iam::123456789012:role/snapshot-role"
  }
}

headers = {"Content-Type": "application/json"}

r = requests.put(url, auth=awsauth, json=payload, headers=headers)

print(r.status_code)
print(r.text)

サンプルコードを自分の環境用に修正したら、自分のローカルで実施しても良いが、今回は CloudShell でやってみた。
コマンドは以下の通り。

$ vi register-repo.py # サンプルコード配置
$ sudo pip3 install boto3 # boto3 インストール
$ sudo pip3 install requests_aws4auth # requests_aws4auth インストール
$ python3 register-repo.py # 実行
200
{"acknowledged":true}

AWS OpenSearch の Kibana ログインに IAM Identity Center (旧AWS SSO) を使う

完全に個人的なメモ。

  1. 対象の OpenSearch クラスターを表示
  2. 「セキュリティ設定」タブを表示し、「編集」ボタン押下
  3. OpenSearch Dashboards/Kibana 用の SAML 認証」欄の SAML 認証を有効化 にチェック
  4. 表示される以下の情報をコピー
    • サービスプロパイダエンティティ ID
    • IdP によって開始された SSO URL
  5. この画面を表示したまま別タブ等で IAM Identity Center を表示
  6. 「アプリケーション > 「アプリケーションを追加」ボタンを押下
  7. カスタム SAML 2.0 アプリケーションの追加 にチェックを入れ「次」ボタンを押下
  8. 「アプリケーションを設定」欄は任意に入力
  9. IAM Identity Center SAML メタデータファイル をダウンロード
  10. 「アプリケーションのプロパティ」欄はセッション時間のみ設定
  11. 「アプリケーションメタデータ」欄
    • メタデータ値をマニュアルで入力する にチェック
    • アプリケーション ACS URL には先程の IdP によって開始された SSO URL を入力
    • アプリケーション SAML 対象者 には先程の サービスプロパイダエンティティ ID を入力
  12. 「送信」ボタンを押下
  13. SSO アプリケーションの追加後、追加されたアプリケーションを選択
  14. 「アクション」 > 「属性マッピングを編集」を選択
  15. 以下の通り入力し、「変更の保存」ボタンを押下

    アプリケーションのユーザー属性 この文字列値または IAM Identity Center のユーザー属性にマッピング 形式
    Subject ${user:subject} unspecified
    Role ${user:groups} unspecified
    User ${user:name} unspecified
  16. 「ユーザーを割り当て」ボタンを押下し、ログインさせたいユーザーを割り当てる

参考

昔受けた面接で失礼に感じた話

自分は IT 業界にいるのだけど、「ユニコーンに乗って」というドラマがやっているのを見て、数年前にとあるスタートアップ企業の面接を受けてとても失礼だと思った話をふと思い出したので書いてみる。

その企業の理念や解決したい課題等に共感し、採用面接に応募。
面談や何度かの面接、体験入社を経て内定をいただくことができた。

問題はその後である。

何が失礼だと感じたか

それは、希望年収に全く届かない額の提示をしてきたことである。

具体的な額は伏せるが、希望年収の65%程度の提示額だったのだ。
仮に希望が600万円なら390万円とか、そういうレベルである。
希望年収は、その当時の現職の年収より低い額を設定していたにもかかわらず、だ。

なぜこの金額なのか質問してみたが、自社の基準にて経験や能力を総合的に判断してこの提示となったということだった。
ちなみに、この転職の時に内定をいただいた他の企業(4社ほど)では、希望年収の95〜110%程度を提示してもらっていたので、そもそもの希望年収が高望みすぎるということはなかったと思っている。

これのどこが失礼か

この企業の基準でそう評価されたのは別に良い。それは企業それぞれで良いのだから。
問題は、この提示額になるとどこかの段階で絶対わかっていたのに条件提示の面談までやらされたことである。

「希望年収が出せなくて心苦しいがオファーさせてくれ」という気持ちで他社のように95%とかの提示をいただくならまだわかる。
自分の希望年収は伝えていたはずで、(65%かどうかはわからずとも)最終的な額が希望より大幅に下回ることなんて途中の段階で絶対にわかっていただろう。
最終的な額が希望より大幅に下回るとわかった段階で、「うちでは希望年収を提示することは難しいから、申し訳ないが選考終了とさせてくれ」と連絡をくれれば良かったのだ。

それなのに最終面接までやらされ、さらには体験入社というイベントにも参加させられ、条件提示でこの顛末である。

こちらは面接をするために現職の予定を調整したり、業務終了後に訪問して面接を受けたりしていた。
体験入社では平日丸1日時間を取ってほしいと言われ、有給休暇も取得して時間を割いたのだ。

ここまで付き合わせておいて65%の提示。
しかもその提示額、募集要項に記載されていた最低年収に少し毛が生えた程度の額である。
こちとら、その当時で15年の業界経験値を持ち合わせておったが?

さすがにバカにしてると思った。

この件についての考察

なぜこのような事が起こったのか、自分の中では3つの仮説がある。

1つ目は、人材の市場価値を知らなすぎる可能性。
前述の通り、現職の年収や当時受けた他数社で希望年収の95〜110%程度を提示いただいたことから、当時の自分の市場価値は概ね認識通りだったと自負している。
しかし、件の企業の採用担当者や経営者は世間の感覚と著しくズレてしまっており、このような判断をしてしまったという仮設。

2つ目は、中途採用が買い手市場だと勘違いしていた可能性。
まぁこれも市場を知らなすぎるに近い話。
IT 業界はある時から人材流動性が高まってきていて、転職希望者は世の中にたくさん出てきている。
件の企業に中途の応募がたくさん来ていて、企業側が優位な立場だと勘違いしていたのではないかという仮設。

3つ目は、やりがい搾取する気満々だった可能性。
この企業は当時メディアに多数露出しており、話題性のある企業だった。
また、事業内容自体も魅力的で、やりがいは非常に高かったように思うし、自分もそう思ったから選考に進んだのだ。
それ故に、提示額がどんなに低くてもやりがいに釣られて入ってくるだろう、という驕りがあったのではないかという仮設。

3つ目が濃厚だと思っているが仮設の域は出ないので、結局どういうつもりでこのような提示をしてきたのかはわからない。

最後に

スタートアップ企業がお金が無いのはわかる。
わかるが、希望年収を大幅に下回る提示になるのなら選考を中断するべき。

この転職で受けた企業の中にはアーリーステージぐらいのスタートアップもあったが、その企業からは「採用できるかどうかは今仕掛けている資金調達次第」という生々しい話をしてくれた。
最終的には「資金調達に難航していて、xx月中に資金調達できそうにないから選考を中断させてほしい」と連絡をいただき、非常に誠実な気持ちを感じた。
(自分がxx月までには転職先を決めるつもりでいると話していたので)

自分も採用面接することもある人間なので気を付けよう。

楽天モバイルから HIS モバイルに乗り換えた

楽天モバイルを使っていたけど、先日の1GB未満0円の終了発表を受けて、乗り換えてみることにした。
まぁ、振り返ってみたら1GB未満の月は無かったので、0円で使えてたことは無いんだけどw
ちょうど1年無料の期間も終わっていたし、0円終了が話題になってたことで乗り換えを考えたきっかけになった感じ。

乗り換え先の検討

結論はタイトルの通り、HIS モバイルにしたのだけど、決めるにあたって現在格安SIMを扱っている数社を比較検討した。

最初、0円終了で話題になっていたのが povo2.0 だったんだけど、調べてみると、恐らくデュアル SIM などで複数の回線を運用をしている人がサブ回線として楽天モバイルを使っていた場合に、そのサブ回線の乗り換え先として povo2.0 を推しているっぽかった。

自分は複数回線を運用したことが無いので憶測だが、複数回線持っているパターンは、メイン回線が何らかの設備障害等で使えなくなった場合の予備としてサブ回線を使うというケースを想定していて、サブ回線は安ければ安いほど運用コストが下がる。
なので、povo2.0 は最安で半年あたり220円で運用できるため、サブ回線を楽天モバイルの1GB未満0円で運用していた人たちからすると、povo2.0 は乗り換え先最有力候補なのだと思う。

自分の場合、メイン回線として楽天モバイルを使っていて、音声通話 SIM がマストで必要である。
そこで、以下の条件で比較してみることにした。☆は必須要件。

  • ☆SIM は 音声通話付き
  • ☆過去12ヶ月間の通信量に合うGBプランの料金
  • 留守番電話サービスの料金比較
  • データチャージ料金(1GBあたり)
  • 繰り越しサービスの有無
  • MNP 転入手数料

過去12ヶ月分の通信量

楽天モバイルでは過去12ヶ月分の利用明細が確認できる。
過去12ヶ月分の通信量を見てみた。

年月 通信量(GB)
2021/05 1.6GB
2021/06 4.1GB
2021/07 2GB
2021/08 1.2GB
2021/09 3.6GB
2021/10 3.2GB
2021/11 3.1GB
2021/12 4GB
2022/01 2.6GB
2022/02 2.7GB
2022/03 3.2GB
2022/04 4.8GB

結果、4GB超えが3回、3GB超えが4回だったので、5GB プランでちょうど良いところががあればそこに乗り換えたい と考えた。

仮に、これと同じ通信量を次の1年も楽天モバイルで使った場合、年間20,636円(税込)である。
これを下回る乗り換え先を検討したい。

各社プラン比較

全社比較したわけではないが、事前に考えていた条件で以下のような比較となった。
(HIS モバイル以外は自信ないけど、多分全部税込金額で書いたハズ…)

HIS モバイルを選んだ理由

プランは「自由自在290プラン」というやつ。 his-mobile.com

なぜ HIS を選んだか。その理由はこちら。

  • 自分の利用実態に合っている 3GB プラン or 7GB プラン、どちらを選んでも最安値
  • 1GB チャージが200円と、これも最安値
  • 通話料金も最安値、しかも専用アプリ不要
  • 留守番電話サービス、改めて確認したら数ヶ月に1〜2件程度だったため、付けないことにした
    • これなら月額払わないで折り返し電話した方が安そうだった
    • 留守電サービスは月額385円だが、30秒あたり9円なので、385円分なら最大で21分ほど電話できる
    • 知り合いへの通話は LINE や FB Messanger 使ってるし、月間で21分も電話しない
  • 手数料が3,300円かかるが、これはまぁ十分に元取れるので

仮に、過去12ヶ月分と同じ通信量(4GB超えが3回、3GB超えが4回)でシミュレーションした場合

  • 3GB プランの場合(チャージ回数合計10回)
    • 基本料金: 770円 × 12ヶ月 = 9,240円
    • チャージ料金: 200円 × 10回 = 2,000円
    • 合計11,240円
  • 3GB プランで 4GB 超え時に低速モードで我慢した場合(チャージ回数7回)
    • 基本料金: 770円 × 12ヶ月 = 9,240円
    • チャージ料金: 200円 × 7回 = 1,400円
    • 合計10,640円
  • 7GB プランの場合(チャージ無し)
    • 基本料金: 990円 × 12ヶ月 = 11,880円
    • 合計11,880円

自分の場合、3GB を少し超える事が多いと考えた場合、3GB プランで足りない月にチャージして使う方がお得だと考えた。
4GB を超えると 7GB プランよりも高くなるので、もし超えた場合は我慢しようと思ったw
最初から 7GB プランにすることも検討したが、繰り越しがないことと、翌月分からではあるがプラン変更が可能なので、翌月の旅行等の予定がわかっていれば、事前にプランを 7GB に変更しておくことができると考えたため、今回は 3GB プランにした。

そうなると、HIS モバイルで運用した場合の年額は 10,640 円となり、楽天モバイルを使い続けた場合(20,636円)と比べておよそ1万円のコストダウンになる試算だ。

料金プランの時点で結構な差がついてるので他社は料金計算まではしなかったが、これが HIS モバイルを選んだ理由である。

その後

斯くして、楽天モバイルMNP 転出手続きをし、HIS モバイルへの申し込みを行い、無事に乗り換えができたのである。
ちなみに、切り替え直後の通信速度はこんな感じだった。(左が平日昼ごろ、右が平日夕方ごろ)

 

また、各社の料金プランを眺めていて思ったのは、もう少し GB の段階を刻んでほしいということ。
イオンモバイルのように1GBずつまで刻まなくても良いのだけど、3, 5, 7, 9 のように 2GB ずつ刻んだりしてほしい。
まぁ敢えてわかりにくくしてるのかもしれないけど。