猫キック

IT関連について投稿

【AWS】【資格】AWS Certified DevOps Engineer - Professional 合格しました.

すみません. 更新してませんでした. . . 明日から本気出します!!

先日、AWS Certified DevOps Engineer - Professional に合格しました. そのため、勉強方法や対策になりそうな資料を複数展開します.



出題内容?

試験範囲 を見ればわかりますが、CI/CDやIaC、サーバレス、可用性と言った内容が出題されそうなのでそちらを重点的に学習した方がいいと思います. ... ていうかこの資料 「付録」 が追加されて出題されるAWSサービスの一覧がわかるようになったんですね. 便利になりましたね〜(小並感).



勉強方法

勉強方法についていくつか紹介します.

1. AWS公式 無料デジタルトレーニングを受講する

AWS公式で無料のデジタルトレーニングを受講することができます. DOPの場合は, [AWS 認定プロフェッショナル] > [DevOps エンジニア – プロフェッショナル] > [試験対策トレーニングを受講する] > [無料のデジタルトレーニングを受ける] で受講できます. とりあえず最初にこのトレーニングを受講して、出題範囲や傾向を掴むのもアリだと思います.


2. AWS Workshopsでサービスに触れてみる

実際に使ってみて、設定内容とかを把握する. AWS WorkshopsはEKSとかECS等, ボリューム満載なため非常にためになる.

3. シナリオを想定する

個人的な意見ですが、多分これが一番勉強になると思います. サービスや分野ごとのシナリオを想定して調べることだと思います. シナリオの想定とは、「〇〇の場合どうやって実現するか」をいくつかのパターンで提案できれば、どのような問題が出ても対処できると思います. 例として、Cloudformationを下記に記します.

# 例
- CloudFormation
  - リソース変更時.           ... 変更セットを作成して反映. 
  - OS以上の上位レイヤの変更は可能か? ... ① Cfn-initでいける. Cfnを利用しないパターンとしては, ②SSM State Manager + Run Command, ③(AutoScalingのばあい)EventBridge経由でRunCommandを実行もあり. また、②③はRunCommandを使用するため、AWS-ApplyAnsiblePlaybooksドキュメントを実行可能. 
  - ローンチ時AnsibleのPlaybook実行呼び出しは可能? ... Cfn上では特に設定しなくてもいいが上記の②③でインスタンス生成時に.
  - テスト                         ... TaskCat. 
  - Linter  ... cfn-lint
  - Validation ... AWS CLI (aws cloudformation validate-template)
  - CI/CD Pipeline                ... CodePipeline上でビルド(CodeBuild上でスタックや変更セットの作成)、テスト(TaskCat), 手動承認、デプロイ(変更セットの適用)は表現できそう.
  - 複数環境での変更
    - マルチリージョンで実施    ... スタックセットを作成し, 複数リージョン反映. DR対策にも.
    - クロスアカウントで実施   ... スタックセットを作成し、複数アカウント反映可能.
    - オンプレミスのリソース    ... できない. けどDCから接続したい要件もあるので、DX経由やVPN経由のネットワークパターンついて学習は必要.
  - よくあるエラー
    - 何かの拍子でリソースを手動で変更し、スタックの更新でエラーが発生.  -> ドリフト機能で検出.スタックを更新しなくて済む.
    - リソース更新/削除できずエラー.     -> 管理対象外のリソースが作成されている? 削除して際実行. 
    - リソース追加でスタック更新時にエラー.  -> 依存関係. ネストして依存関係明確にするとルートやその他のリソースに影響ないかも. 

... こんな感じでメモベースでポイントを押さえて、使ってみたりした方がいいと思います.



4. AWS公式の資料やカンファレンスを観る

「3.」のシナリオで疑問に思ったりデザインパターンとかないかを調べるときに利用します. ためになった資料を紹介します.

Well-Architected Framework

いつものやつ. 監査でCloudTrailログ出力しますとか. AWS SAPの認定でも頻出されるので復習した方がいいと思います.


CI/CD

CodeSeriesの基礎知識はもちろんですが、CI/CDパイプラインでのSource, Build, Test, Deployを含めたワークフローを提案できるようにしないといけません。BlackBelt Online Seminarの動画で基礎を押さえるといいかもしれないです.

以下の動画ではサーバレスアプリケーション上でのCI/CDパイプラインが紹介されてます。

また、扱うリソースによってパイプライン内のロジックが分かれたりするので、最低限これらを押さえ解けばなんとかなるかもしれないです.

また、デプロイの種類(B/G, やCanalry, AllatOnce, Rolling, Immutable)と言ったデプロイ手法も一緒に押さえておいた方がいいと思います.


IaC

CloudFormationはIaCの代表格なので押さえたほうがいいと思います. StackSets(マルチリージョン、マルチアカウント) や Cfn-init(OSレイヤ以上の上位レイヤの設定)と言った機能も、DRや復旧で問われると思われるので、シナリオとして想定した方がいいと思います.


Operations

Systems Manager はシステムの運用改善として非常に役立つことが望まれる機能です. 以下の動画では、クロスアカウント・オンプレミス上でのSSMユースケースが紹介されるためキャッチしておいて損はないと思います.


また、Well-ArchのOperational Excellenceの柱も頻出だと感じたのでそこも踏まえておさらいしておく.


Multi Region, Cross Account, Multi Cloud, Hybrid Cloud

複数のリージョンに跨ってサービスを利用するなら、AWS re:Invent 2019: [REPEAT 2] Architecture patterns for multi-region active-active (ARC213-R2)を参照. マルチリージョン環境におけるAWSサービスの利用をDB, ネットワーク, IaCの観点からまとめられています. DynamoDB Global Tables やCfn Stack Setなどリージョン 間に渡って展開できる機能は押さえておくように.


Cross Account については、各AWSサービスで可能かどうかを自体を参照すればいいですね. Multi Cloud, Hybrid CloudになるとAWS SAP色が強くなる. DirectConnectやTransit Gateway などネットワーク周りの復習をしておいた方がいいと思います.


DR

RPO, RTOが秒単位か分単位か時間単位かによって対策が別れる(レプリケート or クローン環境 or Using Global Service ?)ことが多いです. 下記動画の22:37からはDRについてよくまとまっているので必見.



最後に

頑張ってください!!

【AWS】【Python】Jmespath + フォーマット文字列でフィルタリング

ピンポイントな使い方ですが、Pythonによるjmespathのフィルターについて解説します。

Jmespathとは?

JmespathとはJson形式のドキュメントに対してのクエリ言語です。Jsonの要素を抽出に利用でき、AWS CLI でもフィルターでjmespathが採用されています。 PythonでJmespathを利用する場合、jmespathパッケージをインポートすることで使用できます。

jmespath

Jmespathの基本的な使い方やサンプルは以下のサイトを参考にしていただければ問題ないです。

jmespath.org



ユースケース

例えば、以下のようにAWS SDK for Python 環境下でCWLロググループ/aws/hoge/fuga内のログストリームを取得してログエクスポートする場合、以下のようなコードになります。

import boto3

client = boto3.client('logs')

# ログストリーム取得
log_streams = client.describe_log_streams(logGroupName = "/aws/hoge/fuga",  orderBy = "LastEventTime", descending=True)

# ログエクスポートロジック
for i in log_stream['logStreams']:
     :
     :


上記のlog_streamsの出力結果は以下の通りです。

{
  'logStreams': [
    {
      'logStreamName': '[stream_name_1]', 
      'creationTime': 1622875166781, 
      'firstEventTimestamp': 1622875112000, 
      'lastEventTimestamp': 1625117445000, 
      'lastIngestionTime': 1625118552120, 
      'uploadSequenceToken': '*********************************', 
      'arn': 'arn:aws:logs:[region]:[account_id]:log-group:[log_grp_name]:log-stream:[stream_name_1]', 
      'storedBytes': 0
    }, 
    {
      'logStreamName': '[stream_name_2]', 
        :
    },
      :
  ]
} 


上記のロジックでストリームを取得することは可能です。但し、本日分のログを出力したい等のフィルターをかける場合、上記のコードだけではフィルターしきれません。理由として、ログストリームが実行時間ごとに出力されているケースもあり、ストリーム最終更新時のタイムスタンプlastEventTimestampが数週間前のストリームという場合もあるからです。


そのため、jmespathを利用することで、log_streamsの中身を本日分のストリームのみにフィルターして格納する必要があります。



フォーマット文字列による変数宣言を利用したjmespath

当日のログのみを出力するケースで考えていきます。


実行日の0:00:00のエポックタイムを表した変数lastime_epcを定義。各ログストリームのlastEventTimestampがlastime_epc以上の場合、当日更新があったストリームとみなして、log_streamsに格納するロジックに変更したいと思います。条件分岐ではjmespathを利用します。


pythonでjmespathを利用したい場合は、パッケージjmespathをインポートしてjmespath.search('filter', json_data)の形で利用できます。

import jmespath


filterでは、出力するKeyを選択するとともに、JMESPath Examples — JMESPath の通り、要素の条件式として[?Key (演算子) `値` ]とすれば、要素にフィルターをかけることができます。今回の場合はlastEventTimestampがlastime_epc以上とする。

jmespath.search('logStreams[?lastEventTimestamp >= `lastime_epc`].{ 出力したいValue1, ... }', 実行結果)


但し、上記の条件式はテキスト形式で表現する必要があるため変数を直接条件式に挿入することはできない。そのため、Pythonの場合フォーマット文字列を利用して変数の中身を文字列内に記述する必要があります。フォーマット文字列利用時、文字列内で鉤括弧{}を表現する場合は2文字でエスケープ{{}}することをお忘れないように。改良したものは以下のようになる。

jmespath.search('logStreams[?lastEventTimestamp >= `{}` ].{{ 出力したいValue1, ... }}'.format(lastime_epc), 実行結果)


上記のように実施した結果が、以下の通りとなります。

import boto3
import jmespath    # ADD

# Epoch Time 
toda_epc = '1625097600000'    # ADD

client = boto3.client('logs')

# ログストリーム取得
_log_streams = client.describe_log_streams(logGroupName = "/aws/hoge/fuga",  orderBy = "LastEventTime", descending=True)
log_streams = jmespath.search(
            'logStreams[?lastEventTimestamp >= `{}`].{{ logStreamName: logStreamName, lastEventTimestamp: lastEventTimestamp }}'.format(lasttime_epc),
            _log_streams
        )    # ADD

# ログエクスポートロジック
for i in log_stream['logStreams']:
     :
     :

for, if文を利用することなく、シンプルに中身を抽出できました。



終わりに

CLIの時は変数を条件式に定義できたので勝手が違くて最初は迷いましたが、Pythonの基本に立ち返るとなんともないような内容でした。 しかし、記載されている文献が意外となかったのでここで残しておきます。

【Python】MkDocsを利用したDocumentation用の静的サイト構築

Argo のようなおしゃれなDocを作ってみたいということでMaterial for MkDocsをローカルで作って触ってみたので、セッティングとかの備忘録がてら記事にしたいと思います。

実行環境

  • 実行環境 - pyenv + pyenv-virtualenv
  • Python Version - python 3.8.0



pyenv + pyenv-virtualenv で実行環境設定

既存の環境は汚したくないので新しいpython仮想環境を新規作成して、その上で実行するようにします。

# python ver インストール
pyenv install 3.8.0
pyenv versions 

# 仮想環境sample-mkdocsの作成
pyenv virtualenv 3.8.0 sample-mkdocs
pyenv versions 

# ローカルに適用
cd /path/to/sample-mkdocs
pyenv local sample-mkdocs

# 確認(versionが3.8.0)
python -V 



mkdocs インストール

https://www.mkdocs.org/getting-started/ の通りにmkdocsをインストールする。

さらに、materialテーマを利用するため、https://squidfunk.github.io/mkdocs-material/getting-started/ を参考にmkdocs-materialをインストール。

上記を実行した結果、pip freezeの結果は以下の通り。もし不足パッケージがある場合は適宜インストールをお願いします。

click==8.0.1
ghp-import==2.0.1
importlib-metadata==4.6.0
Jinja2==3.0.1
Markdown==3.3.4
MarkupSafe==2.0.1
mergedeep==1.3.4
mkdocs==1.2.1
mkdocs-material==7.1.9
mkdocs-material-extensions==1.0.1
packaging==20.9
Pygments==2.9.0
pymdown-extensions==8.2
pyparsing==2.4.7
python-dateutil==2.8.1
PyYAML==5.4.1
pyyaml-env-tag==0.1
six==1.16.0
watchdog==2.1.3
zipp==3.4.1

Verを合わせたい場合は、上記の内容をrequirements.txtに出力してインストール。

cat <<EOF > requirements.txt
  :
上記内容
  :
EOF

# install 
pip install -r requirements.txt
# confirm
pip freeze



mkdocs.ymlの編集

mkdocs.ymlを編集することで、コードハイライトやナビゲーションバーの表示等細かいレイアウトが可能になります。一つ一つ解説するのは面倒なので、なるべくコメントにのこしました。小一時間触った結果、良さげな感じに仕上がったのでその時のmkdocs.ymlは以下のようになります。

site_name: hogehoge's Docs
site_url: https://example.com/

docs_dir: "docs"

theme:
  name: material
  locale: ja
  language: ja # メニュー言語を日本語に変更.
  features:
    - search.suggest # Search suggestions
    - navigation.tabs
    - navigation.expand
    - navigation.top
  palette:
    - scheme: default # slate
      primary: light blue
      toggle:
        icon: material/weather-sunny
        name: "ダークモードに切り替え / Switch to dark mode"
    - scheme: slate
      primary: red
      toggle:
        icon: material/weather-night
        name: "ライトモードに切り替え / Switch to light mode"

plugins:
  - search:
      min_search_length: 100 # 検索文字数上限. エラー文も含めたい
      separator: '[\s\-\.]+'  # 検索単語の区切り文字
      lang: ja  # 言語

markdown_extensions:
  - admonition
  - def_list
  - toc:
      permalink: true   # リンク
      slugify: !!python/name:pymdownx.slugs.uslugify_cased  # 日本語をリンクにふくめる場合設定
  - pymdownx.highlight: # ハイライト
      linenums: true # 行番号
      noclasses: true # インラインスタイル
      linenums_style: pymdownx-inline
  - pymdownx.superfences:
      custom_fences:
        - name: mermaid # https://github.com/squidfunk/mkdocs-material/issues/693
          class: mermaid
          format: !!python/name:pymdownx.superfences.fence_div_format
  - pymdownx.details # コンテンツの折り畳み
  - pymdownx.inlinehilite # コードハイライト
  - pymdownx.snippets 
  - pymdownx.keys # キーボードキーの表示 ++文字++

extra_css:
  - https://unpkg.com/mermaid@7.1.2/dist/mermaid.css  # mermaid
extra_javascript:
  - https://unpkg.com/mermaid@7.1.2/dist/mermaid.min.js # mermaid

# Copyright
copyright: "hogehoge © 2021 " # footer copyright

# navigation 
nav:
  - はじめに: index.md
  - About: about.md
  - AWS:
      - Home: aws.md
      - TL;DR: aws/aws_tldr.md
      - Certification:
          - AWS_SAP: aws/certification/aws_certifications.md
      - Models:
          - WebApplicatin:
              - 3Tiers: aws/models/webapp/aws_webapp_3tiers.md
          - Serverless:
              - SinglePageApplication: aws/models/serverless/aws_serverless_spa.md



フォルダ構成

上記 mkdocs.ymlnav のようなmdファイルを用意してあげ、navに追加するだけで反映されます。 今回は下記のように階層を深くしても、navの修正のみですむため、コーディングなしで設定反映でき、インフラ屋の私でもカジュアルに変更を加えられるので、超便利です。

sample-mkdocs/
├── docs/
│   ├── aws/
│   │   ├── certification/
│   │   │   └── aws_certifications.md
│   │   └── models/
│   │       ├── serverless/
│   │       │   └── aws_serverless.md
│   │       └── webapp/
│   │           └── aws_webapp_3tiers.md
│   ├── img/
│   │   └── aws/
│   │       └── sample.png



まとめ

最初はDjangoで作ろうかと考えていたのですが、MkDocs で簡単にセットアップできました。 クラウド上でデプロイするためのアーキテクチャについても今後作成していこうと思います。

【AWS】 CWL + Kinesis Data Firehose + S3 でログエクスポート

私です。

CWL → S3 へログのアーカイブパターンはいくつかありますが、この前、Kinesis Data Firehose 経由でログアーカイブするパターンを設定したため、自身の備忘録も含め、まとめたいと思います。



ログアーカイブについて

AWSにおけるログアーカイブとは、S3/S3 Glacierといったストレージサービスを利用して、ログを保管することです。

ログといっても種類は複数(OS、ミドルウェア、バックエンド、AWSサービス、別プロバイダの実行ログ...)存在します。このようなログは、システムに寄りますが、監査や調査・分析等さまざまな用途で利用されます。

例えば、AWSサービス上で稼働するシステムの場合 1. 監査やログ解析など分析や長期保存が目的の場合はS3へ出力。 2. 障害検知やログ監視が目的の場合はCWLへ出力。 といったように用途に応じて、ログの出力先を適切なサービスに出力する必要があります。

上記2.のログも、コスト面や長期保存や分析を理由に、CWLからS3へ出力しログを保管する必要があるため、その出力をKinesis Data Firehose を利用して実現しようと思います。



アーキテクチャ

全体の構成は以下の図の通り。CWLではロググループ内で サブスクリプションフィルタ を設定してサブスクリプションフィルタ経由で、Kinesis Data Firehoseへ出力します。配信ストリーム側のサーバサイド暗号化(SSE)を利用することで、ストリーム内でデータを暗号化された形で保護します。S3に出力時、データを復号化して出力。S3ではデータ保護の為、SSE-KMSにより、オブジェクトの暗号化を実施するようにします。


f:id:nekodoublekick:20210625230405p:plain



設定


0. 事前準備

  • KMSコンソールを開き、対称のCMK作成。Kinesis用とS3暗号化用で準備.
    • Firehose用のCMK /demo/firehose/defaultkey
    • S3用のCMK /demo/s3/defaultkey


  • S3コンソールを開き、S3バケット作成.
    • バージョニングを有効. SSE-KMSを指定してS3用のCMK/demo/s3/defaultkeyでオブジェクトを暗号化.



1. Kinesis Data Firehose設定

Kinesisコンソールを開き、以下の通りに実施。必要最低限の設定以外は、全てデフォルトで。

  • Delivery stream nameでストリーム名を入力。SourceDirect PUT or other sourcesを指定して、Server-side encryption for source records in the delivery streamを以下のように設定して、Next.

f:id:nekodoublekick:20210625230050p:plain


  • Process recordsではストリームデータの変換が可能。今回は設定しない為、Next.


f:id:nekodoublekick:20210625230123p:plain

  • S3 compressionGZIPを選択。S3 compression and encryption でCMK/demo/s3/defaultkeyを利用してオブジェクトを出力する設定を入力して、Next.

f:id:nekodoublekick:20210625230207p:plain

  • 確認画面.設定内容に誤りがないかを確認して、Next. ストリームが作成される。

  • Firehoseに関連づいたIAMロールを開きポリシーを確認。 S3オブジェクトへEncryptionの許可を設定するため、IAMポリシーにEncryptionアクションを許可。また、/demo/firehose/defaultkey で復号化したストリームデータを、復号化した後、暗号化をするためReEncryptアクションを許可する設定が必要。以下のようなポリシーを追加。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ReEncryptS3Key",
            "Effect": "Allow",
            "Action": [
                "kms:Encrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*"
            ],
            "Resource": "arn:aws:kms:[region]:[account_id]:key/[/demo/s3/defaultkey key_id]"
        }
    ]
}



2. CWL サブスクリプションフィルタ用のIAMロールを作成

CWLサービスがData Firehose ストリームへの配信を許可するためのIAMロールを設定する。 信頼エンティティをlogs.[region].amazonaws.comとして、以下のようなIAMロールを作成する。


{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "logs.ap-northeast-1.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}


次にIAMポリシーを設定. [role_name]には、このポリシーをアタッチするIAMロール名を指定する。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "firehose:*"
            ],
            "Resource": [
                "arn:aws:firehose:[region]:[account_id]:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::[account_id]:role/[role_name]"
            ]
        }
    ]
}



3. CWL サブスクリプションフィルタ作成

サブスクリプションフィルタを作成




確認

  • Firehoseストリームを選択して、Monitoring欄にメトリクスが出力される。データのインカミングとS3へのデリバリーのステータスを確認。
  • ロググループ/aws/kinesisfirehose/[Firehose Stream Name]から、エラー関連のログが出力されないこと。
  • S3バケットを確認。ログが配信されていること。



問題点

当たり前ですが、1つのストリームに複数のCWLグループを選択した場合、S3への出力は、CWLグループごとに出力するわけではなくストリーム単位で出力されます。つまり、複数のCWLを選択したら、出力されるログからはOSログやAWSサービスログが混在した形で出力されます。 他にもログアーカイブの方法としてはLambdaを利用した方法があるため、そちらについても、実施しようと思います。



参考

【AWS】【S3】暗号化形式がSSE-S3形式のみ限定されているログについて

久しぶりに投稿(もしかして飽きてる!?)。最近 Auth0 をいじいじしている私です。


仕事とかでログ設計やS3バケットの設計をしている時、セキュリティの都合でSSE-KMSキーでオブジェクトを暗号化する非機能要件は結構あります。 しかし、全てSSE-KMSで暗号化可能かといったらそうではなく、一部SSE-S3形式でのみ出力することができないサービスがあるので今回はこれについて言及したいと思います。



SSE-KMSの形式で直接出力できないサービス

以下のログはSSE-S3での形式でないとサポートされていない為、注意。


  • S3 アクセスログ ... SSE-S3形式でないと出力できない。
  • CloudFront アクセスログ ... SSE-S3形式でないと出力できない。
  • ELB アクセスログ ... SSE-S3形式出ないと出力できない。
    • S3バケットがELBアカウントID(582318560864)とサービスdelivery.logs.amazonaws.comに対して出力の権限があること。
    • ELBアカウント582318560864は、リージョンごとでアカウントID変わる為、適用するリージョンに応じて変更すること。詳しくはこちら
    • ELBの場合、出力先のS3バケットに以下のようなバケットポリシーがないとアクセスログが出力できないので適用する。(ap-northeast-1上のELBからの出力なので、582318560864)
{
    "Version": "2012-10-17",
    "Id": "AWSConsole-AccessLogs-Policy-xxxxxxxxxxxxx",
    "Statement": [
        {
            "Sid": "AWSConsoleStmt-xxxxxxxxxxxxx",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::582318560864:root"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::[bucket_name]/AWSLogs/[account_id]/*"
        },
        {
            "Sid": "AWSLogDeliveryWrite",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::[bucket_name]/AWSLogs/[account_id]/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        },
        {
            "Sid": "AWSLogDeliveryAclCheck",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "arn:aws:s3:::[bucket_name]"
        }
    ]
}


... ってあれ?



何でSSE-S3だけ?

ここでふと疑問に思ったのが、そもそも上記の暗号化形式がSSE-S3に限定されているのは何故かということ。SSE-KMS形式が選択できない理由とは何か?


色々探してみたんですがそのような記載が載っている文献は見つけられませんでした。。。


おそらくですが、「アクセスログがSSE-S3にのみ限定されているという共通点から、アクセス過多やその他サービスの諸々の処理によるKMS利用によって、簡単に10000 API/s いっちゃうから?」というのが私の結論です。(詳しくはKMSのサービスクォータで)。


上記が正しいならS3サービスでバケットキーのGAがあったので、もしかしたらバケットキーを有効にした場合にのみ、SSE-KMS形式でも暗号化可能になるかもしれないですね? (バケットキーを利用してS3からのAPIコール数を削減できます。詳しくはこちら)

【AWS】AWS Certified Security - Speciality に合格した話

また一つ資格が増えました。私です。

先週の土曜になってしまうのですが、AWS Certified Security - Specialityを受験してきましたので所感も含めて記述したいと思います。


ちなみにスコアは822でした。



勉強時間

  • 1週間。1日約2hの約15hくらい。
  • AWS SAPの取得から日が浅いため、大体はおさらいみたいな感じ。



出題範囲

SCSの出題範囲から推定

  1. インシデント対応
    • AWS の悪用に関する通知を受け取った場合の、セキュリティ侵害が疑われるインスタンスまたは漏洩が疑われるアクセスキーの診断。
    • インシデント対応計画に適切な AWS サービスが含まれていることの確認。
    • 自動的なアラートの構成の確認、およびセキュリティ関連のインシデントや新たな問題に対する対応策の実施。

      IAM(Credential), STS, KMS, Access Advisor, Config, CloudTrail, GuardDuty, SSM, Trusted Advisor, Personal Health Dashboard


  1. ログ収集
    • セキュリティの監視およびアラートの設計と実装。
    • セキュリティの監視およびアラートのトラブルシューティングの実施。
    • ログ収集ソリューションの設計と実装。
    • ログ収集ソリューションのトラブルシューティングの実施。

      監視、検出 ... CWLogs, CWAlarm, Config, CloudTrail, GuardDuty, Macie, Inspector, SecurityHub 分析 ... Athena, Glue, Trusted Advisor, EMR, Redshift, ElasticSearch イベントトリガー、修正 ... CWE, Event Bridge, SSM Automator, SSM Patch Manager, Lambda 出力・配信 ... S3, SQS, SNS, SES, Kinesis Data Firehose, Kinesis Data Streams, CWAgent系 各サービスのエラー内容


  1. インフラストラクチャのセキュリティ
    • AWS のエッジセキュリティの設計。
    • セキュアなネットワークインフラストラクチャの設計と実装。
    • セキュアなネットワークインフラストラクチャのトラブルシューティングの実施。
    • ホストベースのセキュリティの設計と実装。

      CloudFront, Lambda@Edge, WAF, Shield, VPC, VPN, Direct Connect(セキュリティ周り), IAM, Secrets Manager, SSM Parameter Store


  1. IDとアクセスの管理
    • AWS リソースへのアクセスを実現する拡張性の高い認証および権限付与のシステムの設計と実装。
    • AWS リソースへのアクセスを実現する拡張性の高い認証および権限付与のシステムのトラブ ルシューティングの実施。

      認証 ... Cognito, Directory Service, CloudDirectory, SSO 認可 ... IAM(IdP), SSM


  1. データ保護
    • キーの管理および使用に関する設計と実装。
    • キーの管理に関するトラブルシューティングの実施。
    • 保存時および転送中のデータに適用するデータ暗号化ソリューションの設計と実装。

      KMS, CloudHSM, 各種サービスポリシー(バケットポリシーなど)



勉強内容

ここらへんの資料をおさらいしました。出題される/されない関係なく個人的にためになったものは⭐️で。





評価論理の以下の図は、かなり有用。 https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/images/PolicyEvaluationHorizontal.png




所感

  • めちゃくちゃ複雑な条件キーとかが出題されると勘繰っていたが、複雑なものは出てこなかった印象です。しかし「ポリシー周り」の部分は今後もポリシーとか適用する時に、お世話になることが多いですね。
  • KMSについては特に重点的におさらいした方が良いと思いました。暗号化の詳細を確認したい場合にはこちらの資料がいい復習になりました。
  • 範囲がSAPと比較して絞れているので、問題の内容としてはSAPよりも簡単だった印象。けど点数はSAPより低かったです。ナゾや...🤔
  • これまでの試験以上に、日本語/英語の表現が意味不明な問題が多かった。しかし、今回は65問のため何回か読み返しても時間が余ったので時間はあんまり気にしなくてもいいと思います。
  • この季節限定ですが、冷房ギンギンで風がダイレクトに当たってめちゃくちゃ寒かった🥶 のでもし耐えられないようでしたらスタッフを呼び出すなどして対応してもらうことも。


次は、DOPですかね。。CKAも並行ですすめたい。。

【Terraform】 SSMのパブリックパラメータを利用して最新のAMI IDを自動取得する

最近、「正確さ」をあんまり必要としないように仕組みを色々整えようと思う私です。

そんなわけで検証とかでインスタンスたてる際、AmazonLinuxなどのパブリックAMIの最新のAMI IDを自動取得してapplyまで実施するようにしたいと思います。めんどくさい作業は極力減らしたい。

商用利用だとそもそもプライベートAMIを利用するので利用する場面は少ない。 プライベートAMIの場合は、付与されてるタグを対象にフィルターすることでで最新AMI IDを取得可能だが、それについては後日。。

AMI ID確認方法

AMI IDを確認する方法として、1:ec2コマンド, 2:SSMパラメータストア(パブリックパラメータ) の2種類がある。

EC2を利用した確認方法

ec2 describe-imagesを実行すると取得できる。

# Amazonが提供している最新のパブリックイメージを取得
aws ec2 describe-images --owners amazon \
    --filters Name=architecture,Values=x86_64 \
        Name=root-device-type,Values=ebs \
        Name=virtualization-type,Values=hvm

SSMパラメータストア(パブリックパラメータ)からの確認方法

パラメータストアからも 最新のAMIIDを確認することが可能。詳しくはこちら。 最新AMIは、Public Parametersとしてパラメータストアとして予め公開されている。

他にもECS、EKSやAWSサービスのリージョンやエンドポイントについてのあれこれがパブリックパラメータサポートされている

Public ParametersでAMIの一覧を確認するには以下のコマンドを実行することで、PATHとAMI IDを確認することができる

# 最新のAMI取得 (Amazon Linux )
aws ssm get-parameters-by-path \
    --path /aws/service/ami-amazon-linux-latest/ \
    --query 'Parameters[*].{Name:Name,Value:Value}'

# 最新のAMI取得 (Windows Server )
aws ssm get-parameters-by-path \
    --path /aws/service/ami-windows-latest/ \
    --query 'Parameters[*].{Name:Name,Value:Value}'

パブリックパラメーターの一覧を取得するには以下のコマンドを利用する

aws ssm get-parameters-by-path --path /aws/service/list

# appmeshについて確認
aws ssm describe-parameters --parameter-filters "Key=Name, Option=BeginsWith, Values=/aws/service/list/appmesh"

TerraformによるAMI自動取得

data属性でパブリックパラメータを取得し、outputを変数として定義。

# パラメータストア値を参照
data "aws_ssm_parameter" "ami-amzn2" {
  name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}


resource aws_instance amzn2 {
    ami = data.aws_ssm_parameter.ami-amzn2.value
        :
        
}

これで、最新のAMI IDを手動入力して実行する必要はなくなります。

【AWS】【小ネタ】CodeBuild Provisioningで時間がかかる

小ネタです。 タイトル通り通常だと1分以内でCodeBuildのProvisioningフェーズが完了するのですが、久しぶりに動かしたら5分程Provisioningに時間がかかりました。

codebuild slow でggって見るといかに記載。

CodeBuild provisioning very slow most times : aws

CodeBuild によって提供されるドッカーイメージ - AWS CodeBuild

どうやら、古いイメージのバージョンを利用していたことが原因らしいです。

イメージのプロビジョニングは、各イメージの最新バージョンをキャッシュしキャッシュした内容に基づきプロビジョニングするため、これにより古いバージョンを利用すると最新バージョン分のパッチが適用されるため、パッチ適用時間分ビルド時間が長くなります。

Codebuild イメージは常に最新のイメージにするように、設定・メンテナンスを実施する必要がありますね。

【AWS】SSE-KMS カスタマーマスターキー(CMK)によって暗号化されたS3バケットのクロスリージョンレプリケーション

最近はまっていることは、Condition属性の中身をカオスにすることです。

タイトルの通りCMKによって暗号化されたS3バケットクロスリージョンレプリケーションを実施しました。 なるべく最小の権限且つ、CMKの利用を明示して指定する方法を調べたのでハマったことも踏まえて記載。 (むしろハマったことが本題のような気も。。)

構成

CMKでのクロスリージョンレプリケーション(ap-northeast-1 -> ap-northeast-3)を想定。

Setting

1. KMSキーを作成

  • ap-northeast-1上で、crr-tokyo
  • ap-northeast-3上で、crr-osaka

2. S3バケットを作成

  • ap-northeast-1上で、demo-tokyo-crr-01。バージョニングを有効(レプリケーションを実施する上で必須)
  • ap-northeast-3上で、demo-osaka-crr-01。バージョニングを有効

3. IAMロールを作成

  • 信頼エンティティをs3に指定。
  • 送信元のKMSキーで復号化し、送信先のKMSキーを利用してレプリケーションするポリシーを作成してIAMロールにアタッチ。
  • ポリシーは以下の通り。条件キーでKeyAliasとKeyIDをあえて別々で設定しているので実際に利用するならKeyIDで統一するように。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "GetObjectFromSrcBucket",
      "Action": [
        "s3:ListBucket",
        "s3:GetReplicationConfiguration",
        "s3:GetObjectVersionTagging",
        "s3:GetObjectVersionForReplication",
        "s3:GetObjectVersionAcl"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::demo-tokyo-crr-01",
        "arn:aws:s3:::demo-tokyo-crr-01/*"
      ]
    },
    {
      "Sid": "ReplicateToDestBucket",
      "Action": [
        "s3:ReplicateObject",
        "s3:ReplicateDelete",
        "s3:ReplicateTags"
      ],
      "Effect": "Allow",
      "Condition": {
        "StringLikeIfExists": {
          "s3:x-amz-server-side-encryption": [
            "aws:kms",
            "AES256"
          ],
          "s3:x-amz-server-side-encryption-aws-kms-key-id": [
            "arn:aws:kms:ap-northeast-3:${account_id}:key/[大阪のキーID]"
          ]
        }
      },
      "Resource": "arn:aws:s3:::demo-osaka-crr-01/*"
    },
    {
      "Sid": "DecryptSrcRegionKMSKey",
      "Action": [
        "kms:Decrypt"
      ],
      "Effect": "Allow",
      "Condition": {
        "StringLike": {
          "kms:ViaService": "s3.ap-northeast-1.amazonaws.com",
          "kms:EncryptionContext:aws:s3:arn": [
            "arn:aws:s3:::demo-tokyo-crr-01/*"
          ]
        }
      },
      "Resource": [
        "arn:aws:kms:ap-northeast-1:${account_id}:key/alias/crr-tokyo"
      ]
    },
    {
      "Sid": "EncryptDestRegionKMSKey",
      "Action": [
        "kms:Encrypt"
      ],
      "Effect": "Allow",
      "Condition": {
        "StringLike": {
          "kms:ViaService": "s3.ap-northeast-3.amazonaws.com",
          "kms:EncryptionContext:aws:s3:arn": [
            "arn:aws:s3:::demo-osaka-crr-01/*"
          ]
        }
      },
      "Resource": [
        "arn:aws:kms:ap-northeast-3:${account_id}:key/alias/crr-osaka"
      ]
    }
  ]
}

4. レプリケーション設定

送信元バケットレプリケーションルールを設定。設定内容は以下の通り。

{
    "ReplicationConfiguration": {
        "Role": "arn:aws:iam::${account_id}:role/demo-crr",    // IAMロールを指定
        "Rules": [
            {
                "ID": "crr-rule-01",    // レプリケーションルール名を指定
                "Priority": 0,
                "Filter": {
                    "And": {
                        "Prefix": "demo",    // プレフィックスを指定
                        "Tags": [                  // タグ条件を指定
                            {
                                "Key": "IS_REP",
                                "Value": "true"
                            }
                        ]
                    }
                },
                "Status": "Enabled",
                "SourceSelectionCriteria": {
                    "SseKmsEncryptedObjects": {
                        "Status": "Enabled"                      // 暗号化を有効
                    }
                },
                "Destination": {
                    "Bucket": "arn:aws:s3:::demo-osaka-crr-01",      // 送信先バケット
                    "EncryptionConfiguration": {
                        "ReplicaKmsKeyID": "arn:aws:kms:ap-northeast-3:${account_id}:key/alias/crr-osaka"      // 送信先で使用するKMSキーを使用
                    }
                },
                "DeleteMarkerReplication": {
                    "Status": "Disabled"
                }
            }
        ]
    }
}

(補足) IAMで設定した条件キーについての解説。

条件名 役割
s3:x-amz-server-side-encryption オブジェクトに対して暗号化を要求する。今回は条件演算子StringLikeIfExistsと組みわせてオブジェクトは全て暗号化される必要がある
s3:x-amz-server-side-encryption-aws-kms-key-id オブジェクトは特定のKMSキーでないと暗号化できない。(選択する際はkeyIDを指定すること。)
kms:ViaService 特定のサービスからのみアクセス許可
kms:EncryptionContext 暗号化コンテキストの使用。S3の場合はArnを指定。詳しくはこちら

Test

  • オブジェクトをアップロード。 オブジェクトに対してdemo/sample.txtにタグIS_REP : trueを付与する。

  • 送信元demo-tokyo-crr-01のオブジェクトを確認。ReplicationStatusがPENDING -> COMPLETEDになること。

aws s3api head-object --bucket demo-tokyo-crr-01 --key demo/sample.txt
  • 送信先demo-osaka-crr-01のオブジェクトを確認。ReplicationStatusがREPLICAであること。
aws s3api head-object --bucket demo-tokyo-crr-01 --key demo/sample.txt

ハマったこと

なんとなく実施した際にハマったことを記載。 条件キーs3:x-amz-server-side-encryption-aws-kms-key-idで指定するKMSキーはAliasじゃなくKeyIDで指定しないとうまくいかない。(s3系の条件キーでは、aliasからidへの参照権限がないから?) そのため、レプリケーションを実施した際、REPLICATE -> FAILEDの状態になってしまった。

             :
      "Condition": {
        "StringLikeIfExists": {
          "s3:x-amz-server-side-encryption": [
            "aws:kms",
            "AES256"
          ],
          "s3:x-amz-server-side-encryption-aws-kms-key-id": [
            "arn:aws:kms:ap-northeast-3:${account_id}:key/[大阪のキーID]"
          ]
        }
      },
             :

仕事とかではKMSキーIDを指定していましたが、IDかAliasかどちらを指定した方がいいかなんとなくな感じであったので、今回のようにAliasだと参照できないパターンもあるのでkmsキーで指定した方がいいことがわかったのでよかったです(小並感)

References

【その他】ワクチン摂取予約システムの脆弱性から考える脆弱性を発見したときの対処

ワクチン摂取システムの脆弱性(SQLインジェクション)によるシステムの脆弱性の発見を受け、IPAから報告があった。

脆弱性を突く手口、IPA「見つけたらまず開発者やIPA窓口に報告して」 ワクチン予約システムの欠陥巡り - ITmedia NEWS

IPAが提示している届出受付を確認して、どうやって報告するのか何がまずいのかについて、これを期に正しく理解してメモがてら残す。

どうやって報告するの?

最善の対処法は?

  • 情報セキュリティ早期警戒 パートナーシップガイドラインから抽出。
    • 脆弱性等による被害の抑制のため、関係者の推奨される行為をまとめた資料。
    • 今回のケースは「Webアプリケーションの脆弱性」。
    • 発見者の正しいエスカレーションは「脆弱性関連情報の届出受付」にて必要項目を入力し、IPAに報告する。若しくは、運営サイトのお問い合わせ窓口から開発担当者に直接連絡するべきである。
    • 発見者 -> IPA -> ウェブサイト運営者 -> 一般の流れで脆弱性の報告がサイト運営者からなされる。また、脆弱性の公表は。IPA及びJPCERT/CCとの調整の上公表するものであり、今回のように一部報道機関が脆弱性の再現やサイト運営者より前に報道による拡散行為は悪辣な対応であるので無闇に拡散させないこと。公式の声明を待ちましょう。
    • 付録3より、脆弱性をついた攻撃を仕掛けることは、不正アクセス禁止法に抵触する恐れがあるためいたずら目的で攻撃しないこと。

結論

  • 脆弱性を発見したらこちら若しくは、システム管理者のお問い合わせ窓口にて報告。
  • 無闇に拡散しない。サイト運営者からの公式声明があるまで、秘匿する。
  • そもそもテストしとけよこの●● 🤬