Quantcast
Channel: kakakakakku blog
Viewing all 937 articles
Browse latest View live

AWS Lambda MCP Server: Lambda 関数を MCP ツールとして呼び出そう

$
0
0

AWS MCP Servers で2025年4月12日頃にリリースされた(2025.4.2025112152「AWS Lambda MCP Server」を試す.AWS Lambda MCP Server を使うと AWS Lambda 関数を MCP ツールとして呼び出すことができる \( 'ω')/

awslabs.github.io

AWS MCP Servers の GitHub リポジトリに AWS Lambda MCP Server を試せるサンプル「MCP Server Sample Lambda Functions」があったので使ってみる💡

github.com

AWS Lambda 関数をデプロイする

AWS SAM を使って簡単にデプロイできる.ツール側は AWS Lambda 関数があれば OK👌

sam deploy --guidedコマンドを実行して,スタック名は lambda-mcp-server-examplesにした.AWS SAM テンプレートには AWS::Serverless::Functionリソースの FunctionNameプロパティが指定されてなく,AWS Lambda 関数名はスタック名がプレフィックスになる.最終的に以下のように2つの AWS Lambda 関数をデプロイできた.

  • lambda-mcp-server-examples-CustomerInfoFromId-kwdiSQlX2LjF
  • lambda-mcp-server-examples-CustomerIdFromEmail-nElq2nnCGuVb

AWS Lambda 関数 CustomerInfoFromIdは指定した顧客 ID から顧客情報を返す.AWS Lambda 関数 CustomerIdFromEmailは指定したメールアドレスから顧客 ID を返す.サンプル実装としては AWS Lambda 関数から固定のレスポンスを返すようになっているけど(app.py参照),ちゃんと実装するときは Amazon DynamoDB からデータを取得したりと自由に決められる😀

さらに AWS Lambda MCP Server では AWS Lambda 関数の説明 (description) も重要で,MCP ツールとして登録される仕組みになっているとドキュメントに書いてあった📝

  • Customer status from { 'customerId' }
  • Get customer ID from { 'email' }

IMPORTANT: The function name is used as MCP tool name. The function description in AWS Lambda is used as MCP tool description.

Claude Desktop

今回は Claude Desktop を MCP クライアントとして使う.Diagramsで簡易的にアーキテクチャ図を描くとこんな感じになる❗️

そして Claude Desktop に以下の設定を入れておく⚙️ポイントは MCP ツールとして呼び出す AWS Lambda 関数を特定するためのフィルタ条件で,今回は FUNCTION_PREFIXlambda-mcp-server-examples-を設定した.

{"mcpServers": {"awslabs.lambda-mcp-server": {"command": "uvx",
      "args": ["awslabs.lambda-mcp-server@latest"],
      "env": {"AWS_PROFILE": "xxxxx",
        "AWS_REGION": "ap-northeast-1",
        "FUNCTION_PREFIX": "lambda-mcp-server-examples-"
      }}}}

動作確認

あとは以下のように問い合わせをすると AWS Lambda MCP Server 経由で AWS Lambda 関数が呼び出される👌

顧客ID 12345 の顧客情報を教えて!

メールアドレス john.doe@example.com の顧客ID を教えて!

タグを使って AWS Lambda 関数をフィルタする

MCP ツールとして登録する AWS Lambda 関数が増えることを考えると,フィルタ条件として FUNCTION_PREFIXもしくは FUNCTION_LISTを設定するのはちょっと使いにくいように感じた.そこで FUNCTION_TAG_KEYFUNCTION_TAG_VALUEを使うとタグでフィルタできるため試す❗️

ちなみに AWS Lambda MCP Server の実装を読むと,boto3 の list_functions()ですべての AWS Lambda 関数を取得してからフィルタ条件で絞り込むようになっていた.

boto3.amazonaws.com

まず,AWS SAM テンプレートに以下を追加して,AWS Lambda 関数に LAMBDA-MCP-SERVERタグを設定できるようにした✓

Globals:Function:Tags:LAMBDA-MCP-SERVER:true

Claude Desktop の設定も更新した.ポイントは FUNCTION_TAG_KEYFUNCTION_TAG_VALUEを設定しているところ⚙️

{"mcpServers": {"awslabs.lambda-mcp-server": {"command": "uvx",
      "args": ["awslabs.lambda-mcp-server@latest"],
      "env": {"AWS_PROFILE": "xxxxx",
        "AWS_REGION": "ap-northeast-1",
        "FUNCTION_TAG_KEY": "LAMBDA-MCP-SERVER",
        "FUNCTION_TAG_VALUE": "true"
      }}}}

動作確認

変わらず問い合わせできる👌

ちなみに AWS Lambda MCP Server に以下のような実装がある.FUNCTION_PREFIXを指定している場合は MCP ツール名から除去されるようになっていて,キャプチャをよーく見ると実は MCP ツール名が違うという発見もあった💡

  • CustomerInfoFromId-kwdiSQlX2LjF
  • lambda-mcp-server-examples-CustomerInfoFromId-kwdiSQlX2LjF
defsanitize_tool_name(name: str) -> str:
    """Sanitize a Lambda function name to be used as a tool name."""# Remove prefix if presentif name.startswith(FUNCTION_PREFIX):
        name = name[len(FUNCTION_PREFIX) :]


Terraform で aws_instances データソースと for_each を組み合わせて CloudWatch アラームを設定する

$
0
0

複数ある Amazon EC2 インスタンス(Auto Scaling グループ未使用)に対して Terraform で Amazon CloudWatch アラームを設定するコードを実装してみた🧪

実装方針としては aws_instancesデータソースで Amazon EC2 インスタンスを取得して(今回はタグでフィルタリングする),Terraform の for_each メタ引数を使って aws_cloudwatch_metric_alarmリソースを宣言するイメージ💡

developer.hashicorp.com

ちなみに aws_instances データソースのドキュメントには「増減するような一時的なインスタンスを取得するのは非推奨」といったニュアンスの警告が載っている.

It's strongly discouraged to use this data source for querying ephemeral instances (e.g., managed via autoscaling group), as the output may change at any time and you'd need to re-run apply every time an instance comes up or dies.

そして,単なるリソース監視ではなくサービス全体の監視を優先するべきという話が「入門監視」に載っていたりもして,どちらも理解した上で実験してみよう〜というモチベーション \( 'ω')/

サンプルコード1

今回は ApplicationName: sandboxというタグを設定した Amazon EC2 インスタンスを取得して,Amazon EC2 インスタンスごとに CPUUtilizationに対するアラームを設定してみた.アラーム名は CPUUtilization ${each.key}にした.閾値などの値は何でも OK👌

data"aws_instances""instances"{instance_state_names = ["running"]instance_tags = {ApplicationName = "sandbox"}
}

resource"aws_cloudwatch_metric_alarm""cpu_utilization"{for_each = toset(data.aws_instances.instances.ids)

  alarm_name          = "CPUUtilization ${each.key}"namespace           = "AWS/EC2"metric_name         = "CPUUtilization"statistic           = "Average"threshold           = 90comparison_operator = "GreaterThanThreshold"period              = 300evaluation_periods  = 1dimensions = {InstanceId = each.key
  }
}

Amazon EC2 インスタンスを2台起動してからデプロイすると期待通りになった👏

サンプルコード2

もし Amazon EC2 インスタンス ID 以外の値を参照する場合は aws_instanceデータソース(aws_instances ではなく🛑)と組み合わせる必要がある.

以下の例ではアラーム説明に Amazon EC2 インスタンスが起動しているアベイラビリティゾーンを表示できるように CPUUtilization alarm of ${each.key} (${data.aws_instance.instance[each.key].availability_zone})とした👌(特に意味はないけどサンプルとして)

data"aws_instances""instances"{instance_state_names = ["running"]instance_tags = {ApplicationName = "sandbox"}
}

data"aws_instance""instance"{for_each = toset(data.aws_instances.instances.ids)

  instance_id = each.key
}

resource"aws_cloudwatch_metric_alarm""cpu_utilization"{for_each = toset(data.aws_instances.instances.ids)

  alarm_name          = "CPUUtilization ${each.key}"alarm_description   = "CPUUtilization alarm of ${each.key} (${data.aws_instance.instance[each.key].availability_zone})"namespace           = "AWS/EC2"metric_name         = "CPUUtilization"statistic           = "Average"threshold           = 90comparison_operator = "GreaterThanThreshold"period              = 300evaluation_periods  = 1dimensions = {InstanceId = each.key
  }
}

もう一度デプロイして期待通りになった👏

mcp-server-motherduck と DuckDB でデータ分析をしよう

$
0
0

普段から DuckDB を使う機会があって,少し前から気になっていた MotherDuck's DuckDB MCP Server (mcp-server-motherduck)を試してみることにした🦆 mcp-server-motherduck は MotherDuck に統合する機能だけでなく,シンプルにローカル環境の DuckDB を使ってクエリを実行する機能もあって,今回はそっちを試す〜 \( 'ω')/

github.com

MCP クライアントは Claude Desktop / Cline など自由に選ぶことができて,今回は「GitHub Copilot エージェントモード」を使う.

サンプルデータ

DuckDB in Action に出てきたサンプルデータの中から ATP ランキングデータ (ch05/atp/atp_rankings.parquet) を使う🎾

github.com

設定⚙️

ローカル環境の DuckDB を使う場合はインメモリ設定で OK👌

{"mcpServers": {"mcp-server-motherduck": {"command": "uvx",
      "args": ["mcp-server-motherduck",
        "--db-path",
        ":memory:"
      ]}}}

mcp-server-motherduck を試す

プロンプト1

同じプロンプトでも MCP ツールが呼び出されないことがあって,意図的に mcp-server-motherduck を使うように指示してある👌

// mcp-server-motherduck を使う
ch05/atp/atp_rankings.parquet のスキーマ構造を教えて!

mcp-server-motherduck でスキーマ構造を確認できた❗️

内部的には以下のクエリが実行されていた.

DESCRIBE SELECT * FROM'/Users/kakakakakku/ghq/github.com/duckdb-in-action/examples/ch05/atp/atp_rankings.parquet'

プロンプト2

ランキング上位5選手を教えて!

mcp-server-motherduck でランキング上位の選手を取得できた❗️アルカラス🎾

内部的には以下のクエリが実行されていた.

SELECT name_first, name_last, rank, points, ranking_date FROM'/Users/kakakakakku/ghq/github.com/duckdb-in-action/examples/ch05/atp/atp_rankings.parquet'WHERErank<= 5ORDERBY ranking_date DESC, rankASC LIMIT 5

プロンプト3

選手の利き手と成績に相関関係はある?

mcp-server-motherduck で利き手別のデータを取得しつつ,以下の4つの観点から分析できた❗️これは活用の幅がありそうだな〜と思った.

  1. 利き手の分布
  2. 平均ランキング
  3. 最高・最低ランキング
  4. 平均獲得ポイント

キャプチャ以外の分析結果も多く出力されていて,最終的に「まとめ」として以下の考察も生成できた.

データ上では、左利き選手の方が右利き選手よりも平均的に成績が良い傾向が見られます。この「左利きアドバンテージ」は、対戦相手が左利きのプレースタイルに慣れていないことから生じる可能性が考えられます。しかし、最高ランクの選手を見ると、利き手だけが決定的な要素ではなく、テクニック、身体能力、メンタル面など、複数の要素が組み合わさって成功につながっていると考えるべきでしょう。

内部的には以下のクエリが実行されていた.

WITH latest_ranking AS (SELECT * FROM'/Users/kakakakakku/ghq/github.com/duckdb-in-action/examples/ch05/atp/atp_rankings.parquet'WHERE ranking_date = (SELECT MAX(ranking_date) FROM'/Users/kakakakakku/ghq/github.com/duckdb-in-action/examples/ch05/atp/atp_rankings.parquet')) SELECT hand AS利き手, COUNT(*) AS選手数, ROUND(AVG(rank), 2) AS平均ランク, MIN(rank) AS最高ランク, MAX(rank) AS最低ランク, ROUND(AVG(points), 2) AS平均ポイント FROM latest_ranking WHERE hand ISNOTNULLGROUPBY hand ORDERBYCOUNT(*) DESC

プロンプト4

ランキング上位100選手の身長を棒グラフでまとめて!

最後は分析結果をグラフとして出力するプロンプトにしたところ,mcp-server-motherduck でクエリを確認しつつ,GitHub Copilot エージェントモードによって atp_height_analysis.pyが実装された😀そして venv で仮想環境を作って,よくある distutilsのエラーに遭遇して...という感じでエージェントに委ねていたら(バイブコーディング)最終的に棒グラフが出力された📊

最終的に実装された atp_height_analysis.pyでは以下のようなクエリが実行されていて,あとは duckdb / pandas / matplotlib などを組み合わせて棒グラフを出力するようなコードになっていた.

# データの読み込み
query = """WITH latest_ranking AS (  SELECT *   FROM '/Users/kakakakakku/ghq/github.com/duckdb-in-action/examples/ch05/atp/atp_rankings.parquet'  WHERE ranking_date = (SELECT MAX(ranking_date) FROM '/Users/kakakakakku/ghq/github.com/duckdb-in-action/examples/ch05/atp/atp_rankings.parquet')  AND rank <= 100)SELECT   player_id,  rank,  name_first || '' || name_last AS player_name,  heightFROM latest_rankingWHERE height IS NOT NULLORDER BY rank"""

まとめ

MotherDuck's DuckDB MCP Server (mcp-server-motherduck)を試してみた🦆

直接クエリを書かずに DuckDB で Parquet ファイルや CSV ファイルを分析できて便利だった\( 'ω')/

actionlint: GitHub Actions ワークフローの構文をチェックしよう

$
0
0

actionlintを使うと GitHub Actions ワークフローの構文をチェックできる✅️ また run:に指定するシェルを ShellCheckでチェックすることもできて便利❗️actionlint は仕事でも個人プロジェクトでもよく使っているけど,実は今までブログで紹介していなかったな〜と思って,改めてまとめておこうと思った.

github.com

ちなみに actionlint は「GitHub CI/CD 実践ガイド」の第4章でも紹介されている📕

セットアップ

actionlintコマンドをローカル環境で実行するなら Homebrew で OK👌

$ brew install actionlint
$ actionlint --version1.7.7
installed by building from source
built with go1.23.5 compiler for darwin/arm64

github.com

あと actionlint にはウェブですぐに試せる playgroundもあるのでおすすめ \( 'ω')/

rhysd.github.io

実行

actionlintコマンドはデフォルトでリポジトリ内のすべてのワークフローをチェックしてくれるため,基本的にはそのまま実行すれば OK👌

$ actionlint

チェックできる項目は以下にまとまっている📝

github.com

GitHub Actions

actionlint は GitHub Actions に組み込むのも簡単で,以下のようなワークフローになる.あと GitHub Actions の Problem Matchers にも対応していて,プルリクエストに直接コメントすることもできる❗️

👾 .github/workflows/actionlint.yml

name: actionlint

on:pull_request:branches:- main
    paths:- ".github/workflows/**/*.yml"jobs:actionlint:runs-on: ubuntu-latest
    steps:- uses: actions/checkout@v4
      - name: Run actionlint
        run: |
          echo "::add-matcher::.github/actionlint-matcher.json"
          bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
          ./actionlint -color

👾 .github/actionlint-matcher.json

{"problemMatcher": [{"owner": "actionlint",
            "pattern": [{"regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "message": 4,
                    "code": 5}]}]}

動作確認

意図的にエラーが出るようにしてみた😇

  • branchebranches
  • echo ${GITHUB_ACTION_REPOSITORY}echo "${GITHUB_ACTION_REPOSITORY}"

permissions.modelsは未サポート

actionlint は現状まだ permissions.modelsをサポートしてなく,たとえば以下のような権限を実装すると unknown permission scope "models".というエラーが出てしまう.

permissions:contents: read
  models: read
  pull-requests: write

permissions.modelsを使う例は以下の記事にまとめてある❗️

kakakakakku.hatenablog.com

既にプルリクエストは出ているから merge されるとイイな〜💡

github.com

Branch Deploy Action で Terraform をデプロイする (Apply-Before-Merge)

$
0
0

IssueOps でブランチデプロイを実現できる GitHub 公式アクション Branch Deploy Action (branch-deploy)を使って,Terraform の Apply-Before-Merge デプロイ (plan / apply) を自動化してみた❗️

github.com

ちなみに Branch Deploy Actionに関しては2023年7月(約2年前)にまとめたことがある😀

kakakakakku.hatenablog.com

Terraform サンプル

Branch Deploy Action のドキュメント docs/examples.mdに Terraform のサンプルが載っている📝

name: branch-deploy

on:issue_comment:types:[created]# The working directory where our Terraform files are locatedenv:WORKING_DIR: terraform/

# Permissions needed for reacting and adding comments for IssueOps commandspermissions:pull-requests: write
  deployments: write
  contents: write
  checks: read
  statuses: read

jobs:deploy:name: deploy
    runs-on: ubuntu-latest
    if: ${{ github.event.issue.pull_request }} # only run on pull request commentsenvironment: production-secrets # the locked down environment we pull secrets fromdefaults:run:working-directory: ${{ env.WORKING_DIR }} # the directory we use where all our TF files are storedsteps: # The branch-deploy Action- name: branch-deploy
        id: branch-deploy
        uses: github/branch-deploy@vX.X.X

        # If the branch-deploy Action was triggered, checkout our branch- name: Checkout
        if: steps.branch-deploy.outputs.continue == 'true'uses: actions/checkout@v4
        with:ref: ${{ steps.branch-deploy.outputs.sha }}

        # Setup Terraform on our Actions runner- uses: hashicorp/setup-terraform@ed3a0531877aca392eb870f440d9ae7aba83a6bd # pin@v1if: steps.branch-deploy.outputs.continue == 'true'with:terraform_version: 1.1.7 # use the version of Terraform your project uses herecli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}

        # Run Terraform init in our working directory- name: Terraform init
        if: steps.branch-deploy.outputs.continue == 'true'run: terraform init

        # If '.noop' was used, run a Terraform plan- name: Terraform plan
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop == 'true' }}
        id: plan
        run: terraform plan -no-color
        continue-on-error:true # continue on error as we will handle errors later on # If '.deploy' was used, run a Terraform apply- name: Terraform apply
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop !='true' }}
        id: apply
        run: terraform apply -no-color -auto-approve
        continue-on-error:true # continue on error as we will handle errors later on # This step writes the TF plan/apply output to $GITHUB_ENV which the branch-deploy Action will read from and post as a comment on the pull request- name: Terraform plan output
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop == 'true' }}
        env:TF_STDOUT: ${{ steps.plan.outputs.stdout }}
        run: |
          TF_OUTPUT="\`\`\`terraform\n${TF_STDOUT}\n\`\`\`"
          echo 'DEPLOY_MESSAGE<<EOF'>> $GITHUB_ENV
          echo "$TF_OUTPUT">> $GITHUB_ENV
          echo 'EOF'>> $GITHUB_ENV

      - name: Terraform apply output
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop !='true' }}
        env:TF_STDOUT: ${{ steps.apply.outputs.stdout }}
        run: |
          TF_OUTPUT="\`\`\`terraform\n${TF_STDOUT}\n\`\`\`"
          echo 'DEPLOY_MESSAGE<<EOF'>> $GITHUB_ENV
          echo "$TF_OUTPUT">> $GITHUB_ENV
          echo 'EOF'>> $GITHUB_ENV

        # Here we handle any errors that might have occurred during the Terraform plan/apply and exit accordingly- name: Check Terraform plan output
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop == 'true'&& steps.plan.outcome == 'failure' }}
        run: exit 1- name: Check Terraform apply output
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop !='true'&& steps.apply.outcome == 'failure' }}
        run: exit 1

Terraform サンプルを拡張する

今回は Branch Deploy Action のドキュメントに載っている Terraform のサンプルを参考に以下を拡張する❗️

  • plan / apply 結果の出力は GITHUB_ENV環境変数ではなく tfcmtを使う
  • トリガーコメントをデフォルトの .noop.deployから .plan.applyに変更する

tfcmtに関しては最近まとめた📝

kakakakakku.hatenablog.com

なお issue_commentで GitHub Actions ワークフローをトリガーする場合はデフォルトブランチが GITHUB_REFに設定されてしまう仕様になっていた.そこで tfcmt planコマンドと tfcmt applyコマンドを実行するときに --pr ${{ github.event.issue.number }}を指定して期待通りに動くようになった👌

docs.github.com

name: branch-deploy

on:issue_comment:types:[created]permissions:id-token: write
  pull-requests: write
  deployments: write
  contents: write
  checks: read
  statuses: read
  issues: write

jobs:deploy:name: deploy
    runs-on: ubuntu-latest
    env:GITHUB_TOKEN: ${{ github.token }}
      GH_TOKEN: ${{ github.token }}
    if: ${{ github.event.issue.pull_request }}

    steps:- name: branch-deploy
        id: branch-deploy
        uses: github/branch-deploy@v10.4.1
        with:noop_trigger:".plan"trigger:".apply"- name: Checkout
        if: steps.branch-deploy.outputs.continue == 'true'uses: actions/checkout@v4
        with:ref: ${{ steps.branch-deploy.outputs.sha }}

      - uses: aws-actions/configure-aws-credentials@v4
        if: steps.branch-deploy.outputs.continue == 'true'with:role-to-assume: arn:aws:iam::000000000000:role/xxxxx
          aws-region: ap-northeast-1

      - uses: hashicorp/setup-terraform@v3
        if: steps.branch-deploy.outputs.continue == 'true'with:terraform_version: 1.10.3

      - name: Setup tfcmt
        if: steps.branch-deploy.outputs.continue == 'true'run: |
          gh release download -R suzuki-shunsuke/tfcmt v4.14.7 -p tfcmt_linux_amd64.tar.gz
          tar -xzf tfcmt_linux_amd64.tar.gz
          sudo mv tfcmt /usr/local/bin/
          tfcmt --version

      - name: Terraform init
        if: steps.branch-deploy.outputs.continue == 'true'run: terraform init

      - name: Terraform plan
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop == 'true' }}
        id: plan
        run: tfcmt plan --pr ${{ github.event.issue.number }} --patch -- terraform plan -no-color

      - name: Terraform apply
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop !='true' }}
        id: apply
        run: tfcmt apply --pr ${{ github.event.issue.number }} -- terraform apply -no-color -auto-approve

動作確認

期待通りになった👌

.plan (.noop)

.apply (.deploy)

関連記事

同じように Terraform の Apply-Before-Merge デプロイができる Diggerに関しては以下の記事にまとめてある📝

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Infrastructure as Code, 3rd Edition を読んだ / クラウド時代における Infrastructure as Code 関連のトピックを網羅的に学べる一冊

$
0
0

2025年3月に出版された「Infrastructure as Code, 3rd Edition」を読んだ📕

2016年頃に Infrastructure as Code(日本語版)を読んで今でも本棚に置いてあって,2021年に出版された Infrastructure as Code, 2nd Edition は日本語版が出版されたら読もうかな〜思いつつ結局読まなかった(出版もされなかった)という経緯がある.1st Edition と比較すると 3rd Edition は大きく変化していて,クラウド時代における Infrastructure as Code のトピックが網羅的に解説されていて最高の一冊だった❗️

英語だし,そこそこページ数も多くすべてのページを読むのは大変だったけど読んで良かった〜と思う.個人的な「毎日10分間読書」という習慣化時間でコツコツ読んでいて,途中別の本を読んだ日もあったけど1ヶ月ぐらいかかってしまった💨

普段から Thoughtworks ポッドキャストを聴いているんだけど,Infrastructure as code in 2025というエピソードで「Infrastructure as Code, 3rd Edition」が出版されることを知って,すぐ読むことにした.それまでは 3rd Edition が出版されることを知らなくて嬉しい発見だった😀

www.thoughtworks.com

目次

目次から Infrastructure as Code に関連する幅広いトピックが解説されていることがわかると思う❗️

  • I: Foundations
    • 1: What Is Infrastructure as Code?
    • 2: Principles of Cloud Infrastructure
    • 3: Infrastructure Platforms
    • 4: Infrastructure as Code Tools and Languages
  • II: Design
    • 5: Design Principles for Infrastructure as Code
    • 6: Infrastructure Components
    • 7: Designing Deployable Infrastructure Stacks
    • 8: Configuring Infrastructure Stack Instances
    • 9: Integrating Infrastructure Stacks
    • 10: Designing Infrastructure Code Libraries
    • 11: Building Servers as Code
    • 12: Designing Environments
    • 13: Providing Application Runtime Infrastructure
  • III: Delivery
    • 14: Core Infrastructure Delivery Workflows
    • 15: Building and Distributing Infrastructure as Code
    • 16: Implementing Infrastructure Delivery with Pipelines
    • 17: Infrastructure Code Testing Strategy
    • 18: Infrastructure Code Testing Implementation
    • 19: Deploying Infrastructure
    • 20: Changing Existing Infrastructure
    • 21: Governance

www.oreilly.com

X ポスト

読みながら読書メモもたくさん取ったけど,特に印象に残ったところは X にコツコツとポストした❗️

特に良かった Chapter

どの Chapter も良くて,参考になったところや仕事で引用できそうな解説も多かったけど,特に良かった Chapter は以下かな〜と.

  • 1: What Is Infrastructure as Code?
  • 8: Configuring Infrastructure Stack Instances
  • 14: Core Infrastructure Delivery Workflows
  • 17: Infrastructure Code Testing Strategy

1: What Is Infrastructure as Code?

Infrastructure as Code における「誤解」が良かった.普段から Infrastructure as Code を実践していればこういう誤解を感じることはないはずだけど,比較的レガシーなチームを支援していると本当にこういう誤解があって,今後は Infrastructure as Code, 3rd Edition を紹介したり,輪読会をするという選択肢もあるな〜という気づきになった💡

  • Myth: Infrastructure Doesn’t Change Very Often(インフラは頻繁に変更しないという誤解)
  • Myth: We Can Build the Infrastructure First and Automate It Later(インフラ構築を後から自動化できるという誤解)
  • Myth: Speed and Quality Are Trade-Offs(スピードと品質はトレードオフだという誤解)

誤解シリーズで言うと Effective DevOps の「5章 devops に対する誤解とアンチパターン」も良くて,思い出すために5章を読み直したりもした📕

8: Configuring Infrastructure Stack Instances

Patterns for Configuring Stacks(スタックを設定するパターン)というテーマで解説されてて良かった.技術顧問をしているとよく相談を受ける話だな〜と思いながら読んでいた.

  • Configuration in Code
  • Manual Stack Parameters
  • Stack Environment Variables
  • Scripted Parameters
  • Stack Configuration Files
  • Deployment Wrapper Stack
  • Pipeline Stack Parameters
  • Stack Parameter Registry

14: Core Infrastructure Delivery Workflows

Continuous Delivery Principles for Infrastructure as Code(Infrastructure as Code の継続的デリバリー原則)が載っていて良かった.どの原則も当たり前なものではあるけど,Infrastructure as Code に悩んだときは原則に立ち戻るのが良いんだろうな〜と思った.

  • Assume that systems are unreliable.(システムは信頼できないものだと想定する)
  • Make everything reproducible.(すべてを再現可能にする)
  • Avoid snowflake systems.(スノーフレークシステムを避ける)
  • Create disposable things.(リソースを使い捨てる)
  • Minimize variation.(バリエーションを最低限に抑える)
  • Ensure that you can repeat any procedure.(あらゆる手順を繰り返し実行できるようにする)
  • Apply software design principles to your infrastructure code.(インフラストラクチャコードにソフトウェア設計の原則を適用する)

17: Infrastructure Code Testing Strategy

Infrastructure as Code のテストって「何をどこまで」やれば良いの?という相談はよく受けるけど,そういう疑問のアンサーになるような内容になっていて良かった.

たとえば「サブネットの CIDR レンジがあっている?」というテストにはほとんど価値がないという話など,わかるな〜と思いながら読んでいた.他には Swiss Cheese Testing Modelという表現は知らなくて参考になった.簡単に言うと,テストの観点が1つだと気付かずすり抜けてしまうけど,複数段階でテストをすれば気付けるはずという感じ(多層防御的な!).

A suite of low-level tests of declarative code can become a bookkeeping exercise.(宣言的コードに対する低レベルテストは単なる記録作業のようになってしまう)。

en.wikipedia.org

読書メモ抜粋

  • スノーフレークシステム(1st Edition では "スノーフレークサーバ"という表現だった)
  • ClickOps
  • CUPID 原則
  • Infrastructure as Code とチームトポロジー

dannorth.net

まとめ

「Infrastructure as Code, 3rd Edition」を読んで本当に良かった❗️定期的に読み直したい一冊だ〜📕

Infrastructure as Code: Designing and Delivering Dynamic Systems for the Cloud Age (English Edition)

Branch Deploy Action で複数環境に Terraform をデプロイする

$
0
0

Branch Deploy Action (branch-deploy)を使って Terraform をデプロイする仕組みを以下の記事にまとめた📝プルリクエストに .plan.applyとコメントするとデプロイできるという IssueOpsを実現できる👌

kakakakakku.hatenablog.com

前に書いた記事では「1つの AWS 環境」にデプロイしていた.今回は「stg / prd という複数の AWS 環境」にデプロイする仕組みを試す❗️Branch Deploy Action (branch-deploy) は .plan stg.apply stgのように環境名を指定してデプロイする機能もサポートしている👌

GitHub Actions ワークフロー

前に書いた記事に載せた GitHub Actions ワークフローをベースに変更したポイントを以下にまとめる.

まず,branch-deploy のパラメータとして environment_targets: stg,prdを指定した.デフォルトは production,development,stagingになっていた.さらに stgprd以外の環境名が指定された場合はワークフローをエラーで落とすようにした.

次に aws-actions/configure-aws-credentials@v4を使って stg 環境と prd 環境それぞれの IAM Role を紐付けた.GitHub Environments(branch-deploy の environment ではなく GitHub リポジトリ自体の機能)のシークレットから IAM Role の ARN を取得できたらもっと簡単に実装できそう...?(うまくできなかった)

最後に init / plan / apply 実行時には working-directory: ${{ steps.branch-deploy.outputs.environment }}を指定して stgディレクトリもしくは prdディレクトリを作業ディレクトリとして実行できるようにした.今回 Terraform プロジェクトは以下のような簡易的なディレクトリ構成にしてある😀

├── prd
│   ├── backend.tf
│   ├── sqs.tf
│   └── terraform.tf
└── stg
    ├── backend.tf
    ├── sqs.tf
    └── terraform.tf

👾 .github/workflows/branch-deploy.yml

最終的に以下のような GitHub Actions ワークフローにした.

もっと効率的に実装することもできそうだけど...🫠

name: branch-deploy

on:issue_comment:types:[created]permissions:id-token: write
  pull-requests: write
  deployments: write
  contents: write
  checks: read
  statuses: read
  issues: write

jobs:deploy:name: deploy
    runs-on: ubuntu-latest
    env:GITHUB_TOKEN: ${{ github.token }}
      GH_TOKEN: ${{ github.token }}
    if: ${{ github.event.issue.pull_request }}

    steps:- name: branch-deploy
        id: branch-deploy
        uses: github/branch-deploy@v10.4.1
        with:noop_trigger:".plan"trigger:".apply"environment_targets: stg,prd

      - name: Check environment
        if: steps.branch-deploy.outputs.environment !='stg'&& steps.branch-deploy.outputs.environment !='prd'run: exit 1- name: Checkout
        if: steps.branch-deploy.outputs.continue == 'true'uses: actions/checkout@v4
        with:ref: ${{ steps.branch-deploy.outputs.sha }}

      - uses: aws-actions/configure-aws-credentials@v4
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.environment == 'stg' }}
        with:role-to-assume: arn:aws:iam::000000000000:role/xxxxx
          aws-region: ap-northeast-1

      - uses: aws-actions/configure-aws-credentials@v4
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.environment == 'prd' }}
        with:role-to-assume: arn:aws:iam::000000000000:role/xxxxx
          aws-region: ap-northeast-1

      - uses: hashicorp/setup-terraform@v3
        if: steps.branch-deploy.outputs.continue == 'true'with:terraform_version: 1.10.3

      - name: Setup tfcmt
        if: steps.branch-deploy.outputs.continue == 'true'run: |
          gh release download -R suzuki-shunsuke/tfcmt v4.14.7 -p tfcmt_linux_amd64.tar.gz
          tar -xzf tfcmt_linux_amd64.tar.gz
          sudo mv tfcmt /usr/local/bin/
          tfcmt --version

      - name: Terraform init
        if: steps.branch-deploy.outputs.continue == 'true'run: terraform init
        working-directory: ${{ steps.branch-deploy.outputs.environment }}

      - name: Terraform plan
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop == 'true' }}
        id: plan
        run: tfcmt plan --pr ${{ github.event.issue.number }} --patch -- terraform plan -no-color
        working-directory: ${{ steps.branch-deploy.outputs.environment }}

      - name: Terraform apply
        if: ${{ steps.branch-deploy.outputs.continue == 'true'&& steps.branch-deploy.outputs.noop !='true' }}
        id: apply
        run: tfcmt apply --pr ${{ github.event.issue.number }} -- terraform apply -no-color -auto-approve
        working-directory: ${{ steps.branch-deploy.outputs.environment }}

動作確認

.plan

環境名を指定していないため期待通りエラーになった👌

.plan stg

stg 環境で plan を実行できた👌(.plan prdは基本的に同じなので省略)

stg 環境で apply を実行できた👌(.apply prdは基本的に同じなので省略)

Branch Deploy Action (branch-deploy) ドキュメント修正

Branch Deploy Action (branch-deploy) のドキュメント README.mdを読んでいたら Available Commandsに以下のように載っていて「もしかして .noop は環境名を指定できないの!?」と感じてしまった.試しつつ他のドキュメントも読むと実際には .noop でも環境名を指定することができた💡

.deploy
.noop
.deploy to <environment>
.deploy <stable_branch>

README.mdを改善するプルリクエストを送ったらすぐに merge してもらえた🎉

github.com

CDK コードを静的解析できる cdk-nag を試した

$
0
0

ちょっと前に既存の AWS CDK プロジェクトに cdk-nagを導入してみようという話があって,導入前に個人的な検証環境に cdk-nag を導入して試してみた❗️cdk-nag は cfn_nagにインスパイアされていると README に書かれていて,AWS CDK プロジェクトでベストプラクティスに近付くような改善箇所を検出できる.

github.com

Infrastructure as Code, 3rd Edition

最近読んだ「Infrastructure as Code, 3rd Edition」では Chapter.17 Infrastructure Code Testing Strategy の「Offline Static Code Analysis(オフライン静的コード解析)」で以下のように cfn_nag が紹介されていた💡

Terraform’s HCL and CloudFormation templates, such as TFLint, CloudFormation Linter, cfn_nag, and Trivy.

セットアップ

AWS CDK プロジェクトに cdk-nag を組み込むのは簡単で npm installコマンドでセットアップして,エントリーポイントになる bin/xxx.tsAspectsを使って実装すれば OK👌

const app = new cdk.App()
Aspects.of(app).add(new AwsSolutionsChecks({verbose: true}))

ルールセット

現時点では以下の5種類のルールセットがある.詳しくはドキュメント RULES.mdにまとまっている❗️そして今回は1番基本的な AWS Solutions (AwsSolutionsChecks) を試す.

  • AWS Solutions (AwsSolutionsChecks)
  • HIPAA Security (HIPAASecurityChecks)
  • NIST 800-53 rev 4 (NIST80053R4Checks)
  • NIST 800-53 rev 5 (NIST80053R5Checks)
  • PCI DSS 3.2.1 (PCIDSS321Checks)

github.com

動作確認

cdk-nag は cdk synthを実行するタイミングで呼び出される👌

$ npx cdk synth

個人的な検証環境で検出されたエラーの一部を紹介する❗️

🚨 AwsSolutions-S10

AwsSolutions-S10では Amazon S3 バケットで HTTPS (TLS) 経由の暗号化された接続のみを許可していないと検出される.

AwsSolutions-S10: The S3 Bucket or bucket policy does not require requests to use SSL. You can use HTTPS (TLS) to help prevent potential attackers from eavesdropping on or manipulating network traffic using person-in-the-middle or similar attacks. You should allow only encrypted connections over HTTPS (TLS) using the aws:SecureTransport condition on Amazon S3 bucket policies.

今回は aws_s3enforceSSL: trueを追加した👌

const bucket = new aws_s3.Bucket(this, 'xxxxx', {bucketName: 'xxxxx',
    removalPolicy: RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE,
    enforceSSL: true,
})

🚨 AwsSolutions-COG1

AwsSolutions-COG1では Amazon Cognito でパスワードポリシーが要件を満たしていないと検出される.

AwsSolutions-COG1: The Cognito user pool does not have a password policy that minimally specify a password length of at least 8 characters, as well as requiring uppercase, numeric, and special characters. Strong password policies increase system security by encouraging users to create reliable and secure passwords.

今回は aws_cognitopasswordPolicyを追加した👌

const userPool = new aws_cognito.UserPool(this, 'UserPool', {userPoolName: 'sandbox',
    passwordPolicy: {minLength: 8,
        requireLowercase: true,
        requireUppercase: true,
        requireDigits: true,
        requireSymbols: true}})

🚨 AwsSolutions-COG3

AwsSolutions-COG3では Amazon Cognito で Advanced Security Mode が有効化されていないと検出される.

AwsSolutions-COG3: The Cognito user pool does not have AdvancedSecurityMode set to ENFORCED. Advanced security features enable the system to detect and act upon malicious sign-in attempts.

cdk-nag では不要なルールを抑制することもできる.今回は以下のように抑制した.

NagSuppressions.addResourceSuppressions(userPool, [{id: 'AwsSolutions-COG3', reason: 'Cognito Advanced Security Mode is not necessary in my sandbox environment.'},
])

🚨 AwsSolutions-S1

AwsSolutions-S1では Amazon S3 バケットでアクセスログが有効化されていないと検出される.

AwsSolutions-S1: The S3 Bucket has server access logs disabled. The bucket should have server access logging enabled to provide detailed records for the requests that are made to the bucket.

同じく以下のように抑制した.

NagSuppressions.addResourceSuppressions(bucket, [{id: 'AwsSolutions-S1', reason: 'S3 Bucket access logs is not necessary in my sandbox environment.'},
])

🚨 AwsSolutions-VPC7

AwsSolutions-VPC7では Amazon VPC で VPC Flow Logs が有効化されていないと検出される.

AwsSolutions-VPC7: The VPC does not have an associated Flow Log. VPC Flow Logs capture network flow information for a VPC, subnet, or network interface and stores it in Amazon CloudWatch Logs. Flow log data can help customers troubleshoot network issues; for example, to diagnose why specific traffic is not reaching an instance, which might be a result of overly restrictive security group rules.

個人的な検証環境では VPC Flow Logs は必要なく,同じく抑制した.

NagSuppressions.addResourceSuppressions(vpc, [{id: 'AwsSolutions-VPC7', reason: 'VPC Flow Logs is not necessary in my sandbox environment.'},
])

GitHub Actions で実行する

プルリクエストを出したときに GitHub Actions で cdk-nag を実行して,エラーがあったらワークフローを止めることもできる👌シンプルに GitHub Actions ワークフローを実装すると以下のようになる.

name: cdk-nag

on:pull_request:branches:[main]jobs:cdk-nag:runs-on: ubuntu-latest
    steps:- uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:node-version:20cache: npm
      - name: Install dependencies
        run: npm ci
      - name: cdk synth
        run: npx cdk synth

関連記事

aws.amazon.com


Branch Deploy Action でプルリクエストの Approve なしでも例外的にデプロイできる Admins 設定

$
0
0

Branch Deploy Action (branch-deploy) には Adminsという設定がある⚙️ Admins に管理者レベルの権限を持った GitHub アカウント名を指定すると,あくまで「例外的な運用として」Branch protection rule(ブランチ保護ルール)の「Require approvals」を無視してデプロイできるようになる.どういう感じの制御になるのか実際に確認してみた❗️

github.com

準備

README.md に以下のように書いてある.よって,Admins という設定を有効化する前に「Branch protection rule(ブランチ保護ルール)」「Require approvals」を有効化しておく✔️(今回は使い慣れた classic branch protection を使った)

It should be noted that if you do not have pull request approvals enabled in your branch protection rules, then this option will not make a difference either way

GitHub Actions ワークフロー

基本的には以下の記事に載せた GitHub Actions ワークフロー(Branch Deploy Action で Terraform をデプロイする)と同じにしつつ,Branch Deploy Action (branch-deploy) のパラメータとして admins: kakakakakkuを追加した.

kakakakakku.hatenablog.com

GitHub Actions ワークフローの一部を抜粋して載せておく📝

jobs:deploy:name: deploy
    runs-on: ubuntu-latest
    env:GITHUB_TOKEN: ${{ github.token }}
      GH_TOKEN: ${{ github.token }}
    if: ${{ github.event.issue.pull_request }}

    steps:- name: branch-deploy
        id: branch-deploy
        uses: github/branch-deploy@v10.4.1
        with:noop_trigger:".plan"trigger:".apply"admins: kakakakakku

動作確認

admins: kakakakakku設定なし🙅

プルリクエストを作って Approve なし(レビュー未済)だと .planは実行できるけど .apply⚠️ Cannot proceed with deploymentというエラーになった.よって,基本的には Approve をもらってから .applyを実行する流れになる.

admins: kakakakakku設定あり🙆‍♂️

もう一度プルリクエストを作って Approve なし(レビュー未済)のまま .applyを実行する.一般アカウントだと,同じく .planは実行できるけど .apply⚠️ Cannot proceed with deploymentというエラーになった.そして管理者アカウント (@kakakakakku) だと,例外的に .plan.applyも実行できた.

まとめ

実際に確認してみて Adminsという設定のイメージを理解できた👌

Terraform AWS Provider で Amazon Inspector 抑制ルールを設定しよう

$
0
0

Amazon Inspector で特定の CVE を一時的に検出対象から除外したいときに「抑制ルール」を活用できる👌

docs.aws.amazon.com

Terraform AWS Provider 以外の選択肢

しかし最近までは Terraform AWS Provider で「Amazon Inspector 抑制ルール」を設定することができず,以下の選択肢から設定することが多かった.

  • マネジメントコンソール
  • AWS CLI
  • AWS CloudFormation
  • Terraform AWS Cloud Control Provider (awscc)

AWS CLI と awscc で設定する例は過去にブログにまとめた📝

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

Terraform AWS Provider v5.98.0

2025年5月16日にリリースされた Terraform AWS Provider v5.98.0 で待望の aws_inspector2_filterリソースが実装された🎉

github.com

👾 inspector.tf

aws_inspector2_filterリソースを使って CVE の抑制を実装してみた❗️サンプルとして Amazon Linux 2023 Security Advisoriesに載っている CVE を適当にピックアップした.

resource"aws_inspector2_filter""suppression"{name   = "cve-suppression"action = "SUPPRESS"filter_criteria{vulnerability_id{comparison = "EQUALS"value      = "CVE-2025-23244"}vulnerability_id{comparison = "EQUALS"value      = "CVE-2022-46908"}vulnerability_id{comparison = "EQUALS"value      = "CVE-2024-47554"}
  }
}

apply 確認

期待通り👌

まとめ

今後は Terraform AWS Provider の aws_inspector2_filterリソースを積極的に使っていくぞ〜💪

Vibe Coding: CI/CD Level Checker を実装してみた

$
0
0

AWS Prescriptive Guidance にある「The CI/CD litmus test: Is your pipeline fully CI/CD?」は CI/CD の基礎からトランクベースアプローチ・ベストプラクティスまでまとまっていておすすめドキュメントの一つ \( 'ω')/

docs.aws.amazon.com

その中に Litmus test for CI/CD pipelinesという「CI/CD レベル」を測定できる「計20種類」の質問(Yes or No)がある.そして,ドキュメントにもリンクが載っている通り CI/CD litmus test (https://litmus.devops.aws.dev/) という CI/CD レベルを測定するウェブサイトもあった(過去形).今はアクセスできなくなっている...😇 仕事で CI/CD 改善を支援するときに使っていたのに〜

kakakakakku.hatenablog.com

CI/CD Level Checker

前置きが長くなったけど,アクセスできなくなってしまった CI/CD litmus testは Vibe Coding のネタとしてイイな〜と思って実装してみることにした.ウェブサイトのデザインは全然違うけど(前に書いた記事Internet Archive参照),ちゃんと CI/CD レベルを測定できるウェブサイトができあがった💪(今のところ非公開)

作業時間は試行錯誤した時間も含めて2時間だった⌛️

計20問に回答すると

最終的に CI/CD スコアが測定できる

Vibe Coding

今回の作業の流れとツールをまとめておこうと思う.とは言えツールセットは他にもたくさんあるから同じテーマで Vibe Coding してみたいな〜と思ってる😀もっと改善できる流れもあると思う.

  • Step.1: ドキュメント取得 / Firecrawl
  • Step.2: 要件定義 / ChatGPT GPT-4o
  • Step.3: 技術設計 / ChatGPT GPT-4o
  • Step.4: テスト設計 / ChatGPT GPT-4o
  • Step.5: Vibe Coding / GitHub Copilot Agent Mode + Claude 3.7 Sonnet
  • Step.6: git commit / OpenCommit + GPT-4o mini
  • Step.7: 動作確認 / Playwright MCP

🏃‍♂️ Step.1 ドキュメント取得

まずは Firecrawl を使って Litmus test for CI/CD pipelinesウェブサイトの内容を Markdown ファイルに変換した.

www.firecrawl.dev

🏃‍♂️ Step.2 要件定義

次に ChatGPT GPT-4o を使って CI/CD Level Checkerの要件定義をまとめた.Step.1 で変換した Markdown を読ませつつ,計20問を1つの画面で回答させるのではなく「1問ずつ考えながら回答できるような画面遷移に〜」などの要件を壁打ちしながら伝えた.最終的に 要件定義.mdに出力した.

1. 🎯 目的
2. 🧩 機能要件
3. 🖥️ 非機能要件
4. 🔐 セキュリティ要件
5. 📘 利用資料・参考

🏃‍♂️ Step.3 技術設計

同じく ChatGPT GPT-4o を使って CI/CD Level Checkerの要件定義をまとめた.「データベースは使わず完全に静的サイトで〜」「フロントエンドは React ベースで〜」という要件を伝えつつ,他は ChatGPT GPT-4o のおすすめで OK ということにした.ちなみに UI ライブラリのおすすめを聞いたら shadcn/uiとのことだった💡最終的に 技術設計.mdに出力した.

1. 🏗️ アーキテクチャ構成
2. 📦 技術スタック
3. 🌐 ホスティング
4. 🖥️ ローカル開発
5. 🎨 デザイン方針
6. 🚫 除外事項(現時点)

🏃‍♂️ Step.4 テスト設計

Vibe Coding の後にテストをするために,ChatGPT GPT-4o を使ってテスト項目を洗い出した.計20問に対する Yes/No の入力値と CI/CD レベルの期待値をまとめた.最終的に テスト項目.mdに出力した.

## 🧪 Case.1  
期待値:Neutral
## 🧪 Case.2  
期待値:Fully CI/CD
## 🧪 Case.3  
期待値:Not CI/CD

🏃‍♂️ Step.5 Vibe Coding

あとは GitHub Copilot Agent Mode + Claude 3.7 Sonnet に Markdown ファイルを読み込ませて,Vibe Coding を楽しむ❗️実際にサイトにアクセスして,気になったところは変更を指示したりもした.ちょっとした修正だと自分でやりたくなってしまうけど,次に指示したときに戻ってしまうのが嫌だったので,最終的に一度も自分で直すことなく進めてみた👌

github.blog

🏃‍♂️ Step.6 git commit

実装を進めながら,区切りで差分を確認して git commit をした.そのときにコミットメッセージを考えるところも OpenCommitで GPT-4o mini に任せた💪 最近個人では OpenCommit を使うようにしててホント便利だ〜.

github.com

🏃‍♂️ Step.7 動作確認

CI/CD スコアの計算を確認するために テスト項目.mdと Playwright MCP で動作確認をした.以下のように Playwright で画面遷移が進んでいくのを眺めつつ,最終的な CI/CD スコアが正しいことも確認できた❗️

GitHub Copilot Agent Mode でそのまま MCP を呼び出せるから便利だったけど,プロンプトによっては Playwright MCP ではなくローカル環境に Playwright をインストールしようとしてしまうこともあって,調整が必要だった😇

github.com

まとめ

金曜日の午前中に自由時間を捻出できたので,少し前から作りたいな〜と思っていた CI/CD Level Checker を Vibe Coding で実装してみた❗️とにかく楽しかった〜.次は別のツールセットを使った Vibe Coding で CI/CD Level Checker v2を実装してみるぞ〜 \( 'ω')/

GitHub Actions で GitHub Organization のチームに所属しているかどうかを判定する

$
0
0

GitHub Actions でワークフローを実行した GitHub アカウントが GitHub Organization のチームに所属しているかどうかを判定できる tspascoal/get-user-teams-membershipを試してみた❗️tspascoal/get-user-teams-membership では大きく2種類の値を取得できる.

  • teams: 所属しているチーム一覧
  • isTeamMember: 指定したチームに所属しているかどうか

今回は isTeamMemberを試す \( 'ω')/

github.com

準備

検証用の GitHub Organization にチームを2つ(adminsmembers)作った.そして,members チームに自分自身 (@kakakakakku) を所属させた😀

👾 get-user-teams-membership.yml

ワークフローは以下のように実装した.今回はサンプルとして「admins チームに所属していたら echo」「members チームに所属していたら echo」という条件付きのステップにした.

tspascoal/get-user-teams-membership に username / organization / teamを指定すると if: ${{ steps.checkUserInAdmins.outputs.isTeamMember == 'true' }}という構文で取得できて,次のステップで制御に使える👌

name: Check user is in the team

on:workflow_dispatch:jobs:main:runs-on: ubuntu-latest
    steps:- name: Check user is in the admins team
        uses: tspascoal/get-user-teams-membership@v3
        id: checkUserInAdmins
        with:username: ${{ github.actor }}
          organization: xxxxx
          team: admins
          GITHUB_TOKEN: ${{ secrets.FINE_GRAINED_PAT }}
      - name: Echo if user is in the admins team
        if: ${{ steps.checkUserInAdmins.outputs.isTeamMember == 'true' }}
        run: echo "${{ github.actor }} is in the admins team"- name: Check user is in the members team
        uses: tspascoal/get-user-teams-membership@v3
        id: checkUserInMembers
        with:username: ${{ github.actor }}
          organization: xxxxx
          team: members
          GITHUB_TOKEN: ${{ secrets.FINE_GRAINED_PAT }}
      - name: Echo if user is in the members team
        if: ${{ steps.checkUserInMembers.outputs.isTeamMember == 'true' }}
        run: echo "${{ github.actor }} is in the members team"

動作確認

期待通りに Echo if user is in the admins teamはスキップされて,Echo if user is in the members teamは実行された👏 イイ感じ〜

PAT (Personal access tokens)

ちなみに README に書いてある通り,tspascoal/get-user-teams-membershipでは GitHub Organization のチーム情報を取得するために PAT (Personal access tokens) が必要になる.実際に試したところ Personal access tokens (classic)でも Fine-grained personal access tokensでも動いた👌

  • Personal access tokens (classic)なら read:org
  • Fine-grained personal access tokensなら Organization permissions > Members > Read-only

最近(2025年3月)Fine-grained personal access tokens が GA になったこともあって,今回はこっちを使うことにした😀

github.blog

そして README に Fine-grained personal access tokens が使えることも書いてあると良いんじゃないかな〜と考えてプルリクエストも出してみた❗️

github.com

まとめ

GitHub Actions でワークフローを実行した GitHub アカウントが GitHub Organization のチームに所属しているかどうかを判定する場合に tspascoal/get-user-teams-membershipが使える❗️実装も複雑ではなく src/index.jsを読めば GraphQL クエリを実行してる流れも確認できて勉強になる👌

AWS に Dify をデプロイして入門できる「Dify での生成 AI アプリケーション構築ワークショップ」

$
0
0

普段 Difyを使うときはクラウド版を使っているけど,クラウド版以外にセルフホスト版もある👌 AWS に Dify のセルフホスト版をデプロイして Dify に入門できる「Dify での生成 AI アプリケーション構築ワークショップ」を試してみた❗️

catalog.us-east-1.prod.workshops.aws

チャットボット・エージェント・ワークフローなど Dify の基礎を学べるコンテンツとして良かった.さらに Dify のナレッジ (RAG) も試せる.手順はとても丁寧でハマるところはまったくなかった👏 ただし,Dify 自体を試すことが目的なら,AWS に Dify をデプロイする必要はなく,クラウド版を使うのが良いとは思う.

アジェンダ

  1. Dify とは
  2. ワークショップの準備
  3. チャットボットの開発
  4. エージェントの開発
  5. ワークフローの開発
  6. クリーンアップ

誤植

  • Titan Text Emdeddings V2Titan Text Embeddings V2
  • amazon.titan-embedded-text-v2:0amazon.titan-embed-text-v2:0

実施ログ

あとはワークショップを実施しながら残しておいた実施ログを載せておこうと思う😀

🤖 2. ワークショップの準備

AWS CloudFormation で Dify を構築する.AWS CloudFormation テンプレート dify-self-deployment.ymlはそこまで複雑ではなく,Amazon VPC と Amazon EC2 をデプロイしていた.Amazon EC2 インスタンスの user dataでゴニョゴニョしながら最終的に Docker Compose を起動しているところは「なるほど〜」という感じ💡

UserData:
  Fn::Base64: |
      #!/bin/bashmax_attempts=5attempt_num=1success=false
      while [$success=false] && [$attempt_num-le$max_attempts]; do
        sudo dnf install -y git docker
        if [$?-eq0];thenecho"dnf install succeeded"success=true
        elseecho"dnf install $attempt_num failed. trying again..."sleep3((attempt_num++))fidone

      sudo systemctl start docker
      sudo gpasswd -a ec2-user docker
      sudo gpasswd -a ssm-user docker
      sudo chgrp docker /var/run/docker.sock
      sudo service docker restart
      sudo systemctl enable docker
      sudo curl -L"https://github.com/docker/compose/releases/download/v2.28.1/docker-compose-$(uname -s)-$(uname -m)"-o /usr/local/bin/docker-compose
      sudo chmod+x /usr/local/bin/docker-compose
      sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
      cd /opt
      sudo git clone https://github.com/langgenius/dify.git
      cd /opt/dify
      sudo git checkout 1.1.3
      sudo git pull origin 1.1.3cd /opt/dify/docker
      sudo cp .env.example .env
      docker-compose up -d

ワークショップの中でも紹介されていたけど,プロダクション環境で使えるアーキテクチャではないため,より実践的なアーキテクチャは Dify on AWS with CDKを参考にすると良さそう❗️

github.com

そして Amazon Bedrock で使う基盤モデルは大きく4種類だった.

  • Anthropic - Claude 3.5 Sonnet v2
  • Anthropic - Claude 3.5 Haiku
  • Amazon - Titan Text Embeddings V2
  • Cohere - Rerank 3.5

モデルプロバイダー設定

🤖 3. チャットボットの開発

チャットボットで Dify の代表的な操作を体験しよう❗️といった感じの流れだった.「会話の開始(オープナー)」「変数」を試せるのも良かった.

そして,なんと言ってもナレッジ (RAG) を体験できるのが良かった👌 今回はワークショップサイトから PDF をダウンロードして問い合わせの回答に使う.あとナレッジのチャンク設定で「汎用」ではなく「親子」を選択するのは今までやったことがなくて勉強になった〜 \( 'ω')/

  • kintai.pdf(勤怠管理システム入力方法マニュアル)
  • information-system-dept.pdf(情報システム部門の Wiki)

解説ブログも載っていた📝

aws.amazon.com

ナレッジ (RAG) 設定

プロンプトログ

注釈

🤖 4. エージェントの開発

DuckDuckGo プラグインをセットアップして,リサーチエージェントとして検索をするという内容だった.

ログの詳細

🤖 5. ワークフローの開発

手順も長く,そこそこ複雑なワークフローを構築しよう❗️という内容だった.Dify の「質問分類器」を使って RAG・パラメータ抽出・例外処理に分岐する感じで,ブロックごとに解説もされてて理解を深めながら進められるようになっていて良かった.「パラメータ抽出」を体験できるようにワークショップが作られているのも素敵💡

質問分類器

ワークフローの実行結果

まとめ

Dify のセルフホスト版を AWS にデプロイしつつ Dify に入門できる「一石二鳥な」ワークショップだった👏

ちなみにこのワークショップは2024年10月に公開された.公開直後にすぐやってみようと思ったけど,個人アカウントだと Amazon Bedrock のモデルアクセスを有効化できなくて,サポートの回答を待っていたら結局やらなくなってしまったという背景があった😇そのまま寝かせていて,2025年4月にワークショップ手順のアップデートがあったため,改めてやってみることにした❗️

Dify 関連本

2025年5月に Dify 関連本を2冊読んだ.どちらも面白かったからおすすめ❗️特に「ゼロからわかる Dify の教科書」はビジネスパーソンに幅広く刺さりそうな内容になっていて,エンジニアじゃなくても Dify を使ってノーコード(ローコード)な業務効率化ワークフローを作れるっていう自信につながる内容だったから,今回紹介したワークショップとセットで読んでみるのも良さそう😀

OpenCommit: AI に Git のコミットメッセージを考えてもらおう

$
0
0

git commit を実行するときに差分を確認しつつ「どういうコミットメッセージにしたら良いかなぁ〜」と悩むことがある.

そこで LLM (Large Language Models) を使ってコミットメッセージを自動生成できる「OpenCommit」を個人的な検証リポジトリを中心に導入してみた.3週間ほど使ってみて,体験としてはイイ感じ👌

github.com

セットアップ

セットアップは README に載っている通りに実行した👌

$ npm install -g opencommit
$ oco --version3.2.7

次に oco config setコマンドを使って OCO_API_KEYに LLM プロバイダーの API Key を設定する必要があるけど(たとえば OpenAI の API Key など)今回は設定しなかった.後述する .envファイルを使って GitHub リポジトリごとに設定できるためそちらを使う.ちなみに LLM プロバイダーとモデルはデフォルトで OpenAIGPT‑4o miniになっていて,他に Anthropic / Gemini / Ollama などもサポートされている.

👾 .env

OpenCommit を導入する GitHub リポジトリの .gitignore.envを設定しつつ,以下のようにした.必要最低限の設定にしてある👌

OCO_API_KEY=xxx
OCO_GITPUSH=false
OCO_ONE_LINE_COMMIT=true

まず OpenCommit ではコミットメッセージを自動生成した後に「git push する?」というインタラクションがある.個人的には細かく意味のあるステップで git commit をして,まとまってから git push を実行したく不要だな〜と感じたため OCO_GITPUSH=falseで無効化した.README を読むと Push to git (gonna be deprecated)と書いてあるけど,現状まだ代替になる設定が見つからなかったため使うことにした😀

│
◇  Do you want to run `git push`?
│  No
│
└  `git push` aborted

そして OCO_ONE_LINE_COMMIT=trueというオプションを設定すると自動生成されるコミットメッセージをまとめることができる(まとめようと努力する).ちなみに src/prompts.tsを確認すると以下のようなプロンプトが挿入されるようになっている💡

Craft a concise commit message that encapsulates all changes made, with an emphasis on the primary updates. If the modifications share a common theme or scope, mention it succinctly; otherwise, leave the scope out to maintain focus. The goal is to provide a clear and unified overview of the changes in a one single message, without diverging into a list of commit per file change.

とは言え LLM モデルに依存しているところはあって,OCO_ONE_LINE_COMMIT=trueを設定してもファイルごとにコミットメッセージが生成されてしまうこともある.関連する issue もあって参考になる✍

github.com

github.com

実行例

Terraform AWS Provider の v6.0.0-beta1を試したときのコミットメッセージは以下のようになった.

chore(provider.tf): update AWS provider version to 6.0.0-beta1 for compatibility with new features and improvements

Terraform で Amazon Inspector 抑制ルールを設定したときのコミットメッセージは以下のようになった.

feat(inspector.tf): add AWS Inspector filter resource for CVE suppression to manage vulnerabilities effectively

Terraform で Amazon ECS クラスタを追加したときのコミットメッセージは以下のようになった.

feat(ecs): add ECS cluster resource with container insights enabled to enhance monitoring capabilities

Vibe Coding で CI/CD Level Checker ウェブサイトを実装したときのコミットメッセージは以下のようになった.

feat(QuizForm): enhance quiz form with bilingual support for questions and results to improve accessibility for users

gitmoji

また OCO_EMOJIというオプションを使うと gitmojiで標準化された絵文字(10種類)をコミットメッセージの冒頭に追加できる.さらに CLI に --fgmオプションを指定すると全種類の絵文字を対象にできる.

ちなみに CLI のヘルプを確認したら --fgmオプションの説明が載ってなくてプルリクエストを出したりもした👌(Full GitMojiの略というのは最初わからなかった...)

github.com

まとめ

LLM (Large Language Models) を使ってコミットメッセージを自動生成できる OpenCommit❗️

引き続き使っていくぞ〜 \( 'ω')/

listen tcp 0.0.0.0:5000: bind: address already in use. と出たら AirPlay レシーバーを OFF にする

$
0
0

macOS Sequoia を使っていて,Docker で「ポート番号 5000」のコンテナを起動しようとしたら以下のエラーが出た🔥

docker: Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:5000 -> 0.0.0.0:0: listen tcp 0.0.0.0:5000: bind: address already in use.

以下の設定から「AirPlay レシーバー」を OFF にすれば OK👌

一般 > AirDrop と Handoff > AirPlay レシーバー > OFF


CDK で IAM OIDC ID プロバイダーを設定するときは OidcProviderNative を使おう

$
0
0

AWS CDK で IAM OIDC ID プロバイダーを設定するときに OpenIdConnectProviderを使うと内部的に AWS Lambda 関数(カスタムリソース)もデプロイされる仕組みになっている💡とは言えデプロイのために AWS Lambda 関数が増えるのは避けたいな〜(ちょっと嫌だな〜)という気持ちもあったりする.

docs.aws.amazon.com

👾 oidc.ts (OpenIdConnectProvider)

サンプルとして GitHub Actions で使う IAM OIDC ID プロバイダーを設定する場合は以下のようなコードになる.

import{
    Stack,
    StackProps,
    aws_iam
}from'aws-cdk-lib'import{ Construct }from'constructs'exportclass OidcStack extends Stack {constructor(scope:Construct, id:string, props?:StackProps) {super(scope, id, props)

        new aws_iam.OpenIdConnectProvider(this, 'GitHubActions', {url: 'https://token.actions.githubusercontent.com',
            clientIds: ['sts.amazonaws.com'],
        })
    }}

OidcStack-CustomAWSCDKOpenIdConnectProviderCustomR-xxxxxという AWS Lambda 関数がデプロイされていた.

実際にデプロイされた AWS Lambda 関数(カスタムリソース)

OidcProviderNative とは

AWS CDK v2.200.0 で新しく OidcProviderNativeが追加された❗️

github.com

これは AWS CloudFormation の AWS::IAM::OIDCProviderにマッピングされるため AWS Lambda 関数(カスタムリソース)はデプロイされず,シンプルになる👏

docs.aws.amazon.com

👾 oidc.ts (OidcProviderNative)

コードは OpenIdConnectProviderとほとんど同じで OK👌

import{
    Stack,
    StackProps,
    aws_iam
}from'aws-cdk-lib'import{ Construct }from'constructs'exportclass OidcStack extends Stack {constructor(scope:Construct, id:string, props?:StackProps) {super(scope, id, props)

        new aws_iam.OidcProviderNative(this, 'GitHubActions', {url: 'https://token.actions.githubusercontent.com',
            clientIds: ['sts.amazonaws.com'],
        })
    }}

デプロイ確認

期待通りにデプロイできた👌

OidcProviderNative でデプロイできた

まとめ

今後新しく IAM OIDC ID プロバイダーを設定するときは OidcProviderNativeを使おう〜💪

関連記事

kakakakakku.hatenablog.com

Terraform MCP Server: AWS Provider に新しく追加されたリソースのコードを生成する

$
0
0

HashiCorp から公式に提供されている Terraform MCP ServerAWS Terraform MCP Serverではなく🙅‍♂️)の導入検証をする機会があった🧪試したことを簡単にまとめておこうと思う.

github.com

Terraform MCP Server

Terraform MCP Server で使えるツールは現状4種類ある.Terraform Registry から Provider と Module を検索して,ドキュメントからサンプルコードなどの詳細情報を取得できる👌特に Terraform Registry から検索するため「新しく追加された」リソースにも対応できるところがポイント❗️

  • resolveProviderDocID
  • getProviderDocs
  • searchModules
  • moduleDetails

試す

今回は AWS Documentation MCP Serverと Terraform MCP Server を組み合わせて,Amazon Bedrock プロンプト管理をデプロイする Terraform コードを実装してみる😀 Amazon Bedrock プロンプト管理は2025年5月にリリースされた Terraform AWS Provider v5.98.0aws_bedrockagent_promptリソースが追加されている💡

github.com

Step.1

今回は GitHub Copilot Agent Mode + Claude Sonnet 4を使う.まずは以下のプロンプトを使ってAmazon Bedrock プロンプト管理とは何かを学ぶ👌

Amazon Bedrock プロンプト管理とは?

すると AWS Documentation MCP Server の search_documentationread_documentationが実行された.Amazon Bedrock プロンプト管理の概要を理解できた.ふむふむ❗️

Step.2

次に以下のプロンプトを使ってサンプルとして使えそうなプロンプトを取得する👌

Amazon Bedrock プロンプト管理のプロンプトサンプルはドキュメントにある?

するともう一度 AWS Documentation MCP Server の read_documentationが実行されて,複数のプロンプトサンプルを取得できた.今回は「音楽プレイリスト作成プロンプト」を使うことにする.念のため確認して,ちゃんとドキュメントに載っているプロンプトサンプルだった📝

docs.aws.amazon.com

Step.3

最後は以下のプロンプトを使って Terraform コードを生成する👌

では、挙げてもらった「音楽プレイリスト作成プロンプト」を Amazon Bedrock プロンプト管理にデプロイする Terraform コード bedrock.tfを生成して!

すると Terraform MCP Server の resolveProviderDocIDgetProviderDocsが実行された❗️

👾 bedrock.tf

生成された Terraform コードをそのまま貼る \( 'ω')/

ちゃんと Terraform AWS Provider v5.98.0 で新しく追加された aws_bedrockagent_promptリソースを使ったコードになっている👏

# Amazon Bedrock プロンプト管理# 音楽プレイリスト作成プロンプトresource"aws_bedrockagent_prompt""make_playlist"{name            = "MakePlaylist"description     = "音楽プレイリストを作成するプロンプト - ジャンルと曲数を指定して適切なプレイリストを生成します"default_variant = "DefaultVariant"variant{name          = "DefaultVariant"model_id      = "amazon.titan-text-express-v1"template_type = "TEXT"# 推論設定inference_configuration{text{max_tokens     = 2000temperature    = 0.8top_p          = 0.9stop_sequences = []}}# プロンプトテンプレート設定template_configuration{text{text = <<-EOTあなたは音楽の専門家です。以下の条件に基づいて、素晴らしい音楽プレイリストを作成してください。ジャンル: {{genre}}曲数: {{number}}以下の形式でプレイリストを作成してください:

# {{genre}} プレイリスト({{number}}曲)## プレイリストの説明[ジャンルの特徴と選曲の方針を簡潔に説明]## 楽曲リスト1. [アーティスト名] - [曲名]
   - [曲の特徴や選んだ理由を一言][以下、指定された曲数まで繰り返し]## 追加の推奨事項[リスニング環境やその他の推奨事項があれば記載]注意: 実際に存在する楽曲のみを選択し、各楽曲がジャンルに適していることを確認してください。
EOT

        # プロンプト変数の定義input_variable{name = "genre"}input_variable{name = "number"}
      }
    }
  }

  tags = {Environment = "development"Purpose     = "AI-prompt-management"UseCase     = "music-playlist-generation"CreatedBy   = "terraform"}
}

terraform apply を実行する

エラーもなく apply も成功した👏

Terraform MCP Server を使わなかった場合

Terraform MCP Server を使わなかった場合の出力を確認するために同じプロンプトを実行してみる.

Claude Sonnet 4だと aws_bedrock_promptという存在しないリソースになってしまった🙅‍♂️

resource"aws_bedrock_prompt""music_playlist_creator"{name        = var.prompt_name
  description = "AI-powered music playlist creation based on mood, genre, and user preferences"(中略)

ChatGPT o4-mini-highだと Terraform AWS Provider ではなく Terraform AWS Cloud Control Provider (awscc) の awscc_bedrock_promptを使ったコードを生成できた😀これはこれで目的は達成できている \( 'ω')/

resource"awscc_bedrock_prompt""music_playlist"{name        = "music_playlist_prompt"description = "音楽プレイリスト作成プロンプト"(中略)

MOTO_AMIS_PATH: Moto に独自の AMI を登録する

$
0
0

Motoに登録されている AMI (Amazon Machine Image)情報は実際に AWS から取得された値になっていて,頻度高く(毎月)更新されている👌たとえば Moto の us-east-1リージョンや ap-northeast-1リージョンで AMI を検索すると Amazon Linux 2023 AMI 2023.7.20250512.0 x86_64 HVM kernel-6.1が登録されている.

$ docker run --rm-p 5000:5000 --name moto motoserver/moto

# バージニア北部 (us-east-1) リージョン
$ aws ec2 describe-images --endpoint-url http://localhost:5000 \--filters"Name=name,Values=al2023-ami-2023.7.20250512.0-kernel-6.1-x86_64"\--region us-east-1
{"Images": [{"BlockDeviceMappings": [{"Ebs": {"DeleteOnTermination": false,
                        "SnapshotId": "snap-80a08054675345fb6",
                        "VolumeSize": 15,
                        "VolumeType": "standard"},
                    "DeviceName": "/dev/xvda"}],
            "Description": "Amazon Linux 2023 AMI 2023.7.20250512.0 x86_64 HVM kernel-6.1",
            "Hypervisor": "xen",
            "ImageOwnerAlias": "amazon",
            "Name": "al2023-ami-2023.7.20250512.0-kernel-6.1-x86_64",
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "Tags": [],
            "VirtualizationType": "hvm",
            "ImageId": "ami-0953476d60561c955",
            "ImageLocation": "None",
            "State": "available",
            "OwnerId": "137112412989",
            "CreationDate": "2025-06-10T14:57:29.000Z",
            "Public": true,
            "Architecture": "x86_64",
            "ImageType": "machine",
            "KernelId": "None",
            "RamdiskId": "ari-1a2b3c4d"}]}# 東京 (ap-northeast-1) リージョン
$ aws ec2 describe-images --endpoint-url http://localhost:5000 \--filters"Name=name,Values=al2023-ami-2023.7.20250512.0-kernel-6.1-x86_64"\--region ap-northeast-1
{"Images": [{"BlockDeviceMappings": [{"Ebs": {"DeleteOnTermination": false,
                        "SnapshotId": "snap-ce820459498b5678a",
                        "VolumeSize": 15,
                        "VolumeType": "standard"},
                    "DeviceName": "/dev/xvda"}],
            "Description": "Amazon Linux 2023 AMI 2023.7.20250512.0 x86_64 HVM kernel-6.1",
            "Hypervisor": "xen",
            "ImageOwnerAlias": "amazon",
            "Name": "al2023-ami-2023.7.20250512.0-kernel-6.1-x86_64",
            "RootDeviceName": "/dev/xvda",
            "RootDeviceType": "ebs",
            "Tags": [],
            "VirtualizationType": "hvm",
            "ImageId": "ami-0c1638aa346a43fe8",
            "ImageLocation": "None",
            "State": "available",
            "OwnerId": "137112412989",
            "CreationDate": "2025-06-10T14:57:29.000Z",
            "Public": true,
            "Architecture": "x86_64",
            "ImageType": "machine",
            "KernelId": "None",
            "RamdiskId": "ari-1a2b3c4d"}]}

仕組みとしては GitHub Actions ワークフロー .github/workflows/data-update_ssm-default-amis.ymlscripts/ssm_get_default_amis.pyを実行して,最終的にリージョンごとに Amazon Linux 関連の AMI 情報を moto/ec2/resources/latest_amis/*.jsonに保存している感じ〜❗️

github.com

独自の AMI を登録する

さらに Moto には独自の AMI を登録する仕組みもあって,環境変数 MOTO_AMIS_PATHに JSON ファイルを指定すると自動的にロードされるようになっている👌テストで使うダミーデータとして登録できたりする.

If you require specific AMIs to be available during your tests, you can provide your own AMI definitions by setting the environment variable MOTO_AMIS_PATH to point to a JSON file containing definitions of the required AMIs. No other AMI’s will be loaded if this environment variable is set.

docs.getmoto.org

👾 amis.json

サンプルとして Sample-AMI-2025-06 (ami-99999999999999999)という AMI 情報を ~/amis.jsonに設定しておく.

[{"ami_id": "ami-99999999999999999",
    "state": "available",
    "public": true,
    "owner_id": "999999999999",
    "image_location": "None",
    "sriov": "simple",
    "root_device_type": "ebs",
    "root_device_name": "/dev/sda1",
    "description": "Sample-AMI-2025-06",
    "image_type": "machine",
    "platform": "windows",
    "architecture": "x86_64",
    "name": "Sample-AMI-2025-06",
    "virtualization_type": "hvm",
    "hypervisor": "xen"
  }]

そして,以下のように環境変数 MOTO_AMIS_PATH~/amis.jsonを指定して Moto (Server Mode) を起動する.

$ docker run --rm-p 5000:5000 \--name moto \-v ~/amis.json:/moto/amis.json \-eMOTO_AMIS_PATH=/moto/amis.json \
  motoserver/moto

すると ~/amis.jsonが優先的にロードされるため,以下のように Sample-AMI-2025-06を取得できるようになる❗️

# バージニア北部 (us-east-1) リージョン
$ aws ec2 describe-images --endpoint-url http://localhost:5000 \--region us-east-1
{"Images": [{"BlockDeviceMappings": [{"Ebs": {"DeleteOnTermination": false,
                        "SnapshotId": "snap-4cfec037fcda8435e",
                        "VolumeSize": 15,
                        "VolumeType": "standard"},
                    "DeviceName": "/dev/sda1"}],
            "Description": "Sample-AMI-2025-06",
            "Hypervisor": "xen",
            "ImageOwnerAlias": "amazon",
            "Name": "Sample-AMI-2025-06",
            "RootDeviceName": "/dev/sda1",
            "RootDeviceType": "ebs",
            "Tags": [],
            "VirtualizationType": "hvm",
            "ImageId": "ami-99999999999999999",
            "ImageLocation": "None",
            "State": "available",
            "OwnerId": "999999999999",
            "CreationDate": "2025-06-12T16:01:29.000Z",
            "Public": true,
            "Architecture": "x86_64",
            "ImageType": "machine",
            "KernelId": "None",
            "RamdiskId": "ari-1a2b3c4d",
            "Platform": "windows"}]}# 東京 (ap-northeast-1) リージョン
$ aws ec2 describe-images --endpoint-url http://localhost:5000 \--region ap-northeast-1
{"Images": [{"BlockDeviceMappings": [{"Ebs": {"DeleteOnTermination": false,
                        "SnapshotId": "snap-8eb68c280c406e39a",
                        "VolumeSize": 15,
                        "VolumeType": "standard"},
                    "DeviceName": "/dev/sda1"}],
            "Description": "Sample-AMI-2025-06",
            "Hypervisor": "xen",
            "ImageOwnerAlias": "amazon",
            "Name": "Sample-AMI-2025-06",
            "RootDeviceName": "/dev/sda1",
            "RootDeviceType": "ebs",
            "Tags": [],
            "VirtualizationType": "hvm",
            "ImageId": "ami-99999999999999999",
            "ImageLocation": "None",
            "State": "available",
            "OwnerId": "999999999999",
            "CreationDate": "2025-06-12T16:02:17.000Z",
            "Public": true,
            "Architecture": "x86_64",
            "ImageType": "machine",
            "KernelId": "None",
            "RamdiskId": "ari-1a2b3c4d",
            "Platform": "windows"}]}

関連記事

kakakakakku.hatenablog.com

kakakakakku.hatenablog.com

エスケープハッチ: CDK の L2 Constructs "sns.Topic"で未サポートのデータ保護ポリシーを設定する

$
0
0

AWS CDK で L2 Constructs を使いつつ,L2 Constructs 未サポートのプロパティを L1 Constructs にキャストして設定するテクニックを「エスケープハッチ」と言う.ドキュメントに詳しく載っている📝

docs.aws.amazon.com

「エスケープハッチ」というテクニック自体は知っていたけど,今まで必要になる場面にほとんど遭遇してなく,実は使ったことがなかった😅せっかくなら試してみよう〜ということで試したログを簡単にまとめておこうと思う \( 'ω')/

Amazon SNS トピックの「データ保護ポリシー」

今回は Amazon SNS トピックの「データ保護ポリシー」をテーマにする❗️

docs.aws.amazon.com

「データ保護ポリシー」は現状だと L2 Constructs の sns.Topicには実装されてなく,L1 Constructs の sns.CfnTopicでは dataProtectionPolicyプロパティとして設定できる.

docs.aws.amazon.com

docs.aws.amazon.com

ちなみに L2 Constructs に dataProtectionPolicyを追加してくれ〜という issue は既にあって,様子を見てると近々サポートされそうな気配がある👀

github.com

👾 lib/sns-escape-hatches.ts

以下のように実装した👌ポイントは Amazon SNS トピックを L2 Constructs で実装しつつ,L1 Constructs にキャストしているところ.すると cfnTopic.dataProtectionPolicyで L2 Constructs では未サポートの「データ保護ポリシー」を設定できるようになる.ちなみに今回はサンプルとして「拒否」を設定している🙅

import{
    Stack,
    StackProps,
    aws_sns,
}from'aws-cdk-lib'import{ Construct }from'constructs'exportclass SnsEscapeHatchesStack extends Stack {constructor(scope:Construct, id:string, props?:StackProps) {super(scope, id, props)

        const topic = new aws_sns.Topic(this, 'Sandbox', {topicName: 'sandbox-topic',
        })

        const cfnTopic = topic.node.defaultChild asaws_sns.CfnTopic

        cfnTopic.dataProtectionPolicy =  {'Name': 'SandboxDataProtectionPolicy',
            'Description': 'Sandbox Data Protection Policy',
            'Version': '2021-06-01',
            'Statement': [{'Sid': 'SandboxDataProtectionPolicyStatementInbound',
                    'DataDirection': 'Inbound',
                    'Principal': ['*'],
                    'DataIdentifier': ['arn:aws:dataprotection::aws:data-identifier/Address',
                        'arn:aws:dataprotection::aws:data-identifier/AwsSecretKey',
                    ],
                    'Operation': {'Deny': {}}}],
        }}}

デプロイ確認

cdk deployを実行して Amazon SNS トピックを確認すると期待通りに「データ保護ポリシー」を設定できていた👏

AWS CDK の実践的なトピックがまとまった「マスタリング AWS CDK」を読んだ

$
0
0

「マスタリング AWS CDK」を読んだ📕

著者の経験から語られる実践的なトピックが満載の一冊だった❗️AWS CDK を使っていると悩むポイントが多く解説されていて,AWS CDK 初学者から日々活用してる人まで幅広く読める内容だった.また本書を読んでいて 積極的に活用すべきです。 / ベストです。 / 推奨しています。 / 基本利用しないほうがよいです。という表現が多く出てくるところも印象的だった.

techbookfest.org

目次

  • 1章: はじめに
  • 2章: AWS CDK の開発環境セットアップ
  • 3章: AWS CDK について
  • 4章: CDK で Lambda を実装してみよう
  • 5章: CDK で ECS を実装してみよう
  • 6章: CDK のテスト
  • 7章: 型によるパラメータ管理と環境分離
  • 8章: アーキテクチャ設計と Stack 構成
  • 9章: アーキテクチャ設計の実践
  • 10章: CI/CD パイプライン

L2.5 Construct

本書を読んでいたら NodejsFunctionなどは L2.5 Constructって呼ばれるって書いてあってこれは知らなかった💡

docs.aws.amazon.com

調べてみたら AWS Black Belt Online Seminar「AWS CDK Basic #1」にも L2.5 constructsという表現が書いてあった.へぇ❗️

• より特定のシナリオに合わせて単⼀リソースを抽象化した L2.5 constructs も存在

エスケープハッチ

3章のコラムに「エスケープハッチ」の紹介が載っていた.エスケープハッチ自体は知っていたけど実は今まで使ったことがなくて,本書を読みながら気になって試した記事も書いた \( 'ω')/

kakakakakku.hatenablog.com

テスト戦略

IaC (Infrastructure as Code) のテスト・AWS CDK のテストは悩みポイントも多く,第6章はイイ内容だった.AWS CDK で宣言的なコードを実装していると,Fine-grained Assertionsで想定したパラメータが設定されているかどうかをテストするのは効果的ではないと書いてあったりもして「それな〜」という共感ポイントも多かった.

印象的だったのは本書では「スナップショットテスト」基本的には導入を強くお勧めします。と書かれているところだった.個人的には効果的に使えたことがなく,導入したけど消してしまったこともあった.リファクタリングをするときは cdk diffを実行すれば良いしな〜と思ったりもしていて.とは言え改めて導入を検討してみたいと思った😀

さらに本書で「ポリシー検証」として紹介されていた cdk-nagは便利で最近よく使ってる.テストという観点以外に「お作法を学ぶ」ために使うこともできて「あ〜こういう設定を考慮する必要があるんだな〜」という気付きにつながるので,結果不要だったら抑制してしまえば OK👌cdk-nag に関しては最近ブログにまとめた.

kakakakakku.hatenablog.com

スタック設計

AWS CDK プロジェクトのスタック設計も悩みポイントの一つだと思う.本書では第8章に どんな状況にも当てはまる万能なアーキテクチャは存在しません。と書いてありつつも「こういう考え方はどうか」という具体的な例が紹介されていて良かった.第8章と第9章は特に読みたい人が多そうだな〜と感じた❗️

AWS CDK の強い参照 (Strong Reference) の大変さも紹介されていて「あ〜」という気持ちに😇前に参照を消すにも消せなくなって苦労した過去を思い出してしまった.他にも Construct ベースのクラス分割や Lambda / ECS を使ったアーキテクチャのディレクトリ構成例なども参考になる.なお,本書に載っているコードは GitHub に公開されていて,イメージを掴めると思う.

github.com

あと個人的には Dify on AWS with CDKの実装を最近読んでキレイだな〜と感じた👏 本書の GitHub リポジトリも含めて,何かしら参考にできるお手本を持っておくと良さそう.

github.com

気付いた誤植

  • P.10 200 回以上の更新されています。200 回以上も更新されています。
  • P.12 把握することを難しくなります。把握することが難しくなります。
  • P.15 AWS CDK を生まれました。AWS CDK が生まれました。
  • P.82 AWS 予約アドレス�→ 特殊文字?
  • P.118 新鋭申請
  • P.124 Eventbridge ScheduleEventBridge Scheduler
  • P.124 DynamoDB StreamDynamoDB Streams
  • P.140 パブリックリポジトリ出ない場合パブリックリポジトリではない場合
  • P.142 ID を AWS_ACCOUNT_ID を設定してください。ID を AWS_ACCOUNT_ID に設定してください。
  • P.158 LambadaLambda

まとめ

AWS CDK の基礎から実践まで学べる「マスタリング AWS CDK」良かった📕あと個人的には us-east-1 リージョン(バージニア北部)の AWS Certificate Manager (ACM) 証明書を管理しようとすると面倒になる気がしてて,他にもありそうな「AWS CDK あるあるとその対策」をもっと読みたいな〜と思ったりもした😀

kakakakakku.hatenablog.com

ちなみに AWS CDK に限らず IaC (Infrastructure as Code) 全体のトピックを網羅的に学びたかったら「Infrastructure as Code, 3rd Edition」もおすすめしたい😀最近読んで最高だった.

kakakakakku.hatenablog.com

Viewing all 937 articles
Browse latest View live