【RISSが実践】Astro × AWS Serverlessで作る!安全で爆速な「自分専用・エンジニア道具箱」の構築とAPIセキュリティ対策


  1. はじめに インフラ・セキュリティエンジニアとして日々の業務(RHELの脆弱性調査・パッチ適用や、行政機関向けフォレンジック検証など)を行っていると、「ランダムなセキュアパスワードの生成」や「テキストのBase64エンコード/デコード」といったちょっとしたツールをサクッと使いたい場面が多々あります。

皆さんはこういった時、Web上で検索して一番上に出てきた無料ツールを使っていませんか?しかし、セキュリティの観点から見ると、これらには以下の懸念があります。

データの機密性: ブラウザに入力した文字列(特にデコード前の機密情報など)が、裏側でサーバーに送信・保存されていないという確証がない。

可用性とUX: 広告が多くて目的のボタンが押しづらかったり、サイトのレスポンスが遅かったりする。

「他人のサーバーに依存せず、自分が100%コントロールできる安全なツール環境が欲しい」——そう考えた私は、情報処理安全確保支援士(登録セキスペ)としての知見と、AWSアーキテクチャの設計ノウハウを活かし、「絶対に安全で、爆速で動く自分専用のツール群(俺の道具箱)」を自作することにしました。

本記事では、Astro(フロントエンド)とAWS Lambda(バックエンド)を用いたサーバーレス構成の実装手順に加え、単なるHow-to記事では省かれがちな「不正アクセスや高額課金(Economic DoS)を防ぐための、実務レベルのAPIセキュリティ対策」を中心に解説します。

  1. システム構成:サーバーレスによるモダンなWeb基盤 今回の「俺の道具箱」を支えるアーキテクチャの全体像です。

構成要素 Frontend: Astro (Cloudflare Pagesによる高速配信)

API Layer: Amazon API Gateway (REST API)

Backend Logic: AWS Lambda (Python 3.12)

Security: API Throttling, Strict CORS, Server-side Validation

この構成を選んだ理由 インフラエンジニアとして重視したのは、「運用の手離れの良さ」と「コストパフォーマンス」、そして「セキュリティ(Security by Design)」の3点です。

① 完全サーバーレスによるゼロメンテナンス EC2のようにOS(Linux等)のパッチ当てやミドルウェアの管理を必要とせず、使った分だけ課金されるLambdaを採用しました。維持コストをほぼゼロに抑えつつ、インフラの保守運用から解放されます。

② SSG(静的サイト生成)による爆速レスポンス Astroを採用することで、ツール画面のUIはビルド時に事前生成されます。ユーザーが画面を開く際は超高速な静的ファイルが返り、「変換ボタン」を押した瞬間だけ軽量なLambda APIを叩くという無駄のない動きを実現しています。

  1. 実装のポイント:安全な非同期処理

ツールの実行にはブラウザ標準のFetch APIを使用しています。単にデータを取得するだけでなく、インフラエンジニアらしい「異常系への配慮」をコードに反映させています。

JavaScript

try {
    const response = await fetch(API_URL + "?length=" + length + "&symbols=" + useSymbols);
    
    if (!response.ok) {
        throw new Error("HTTP error! status: " + response.status);
    }
    
    const data = await response.json();
    resultInput.value = data.password;
} catch (error) {
    console.error("API呼び出しエラー:", error);
    alert("通信に失敗しました。後ほど再度お試しください。");
}

UIデザインにはTailwind CSSを活用し、快適に操作できるレスポンシブな設計にしました。

  1. バックエンドの実装:AWS Lambda × Python 3.12 バックエンドのロジックは、保守性の高いPython 3.12で実装しました。

暗号学的に安全な乱数生成 「パスワード生成」ツールにおいて最も重要なのは乱数の質です。標準のrandomモジュールは推測されるリスクがあるため、本ツールでは暗号学的に強い乱数を生成する secrets モジュールを採用しています。

Python

import secrets
import string
import json

def lambda_handler(event, context):
    chars = string.ascii_letters + string.digits
    use_symbols = event.get('queryStringParameters', {}).get('symbols') == 'true'
    
    if use_symbols:
        chars += "!@#$%^&*"

    password = ''.join(secrets.choice(chars) for _ in range(16))
    
    return {
        'statusCode': 200,
        'body': json.dumps({'password': password})
    }

RHELの脆弱性対応の実務で培った「安全なライブラリ選定」の習慣を反映させています。

  1. 【メイン】登録セキスペ視点のセキュリティ対策(多層防御) 個人ツールとはいえ、Web上にAPIを公開する以上、攻撃や悪用(タダ乗り)のリスクはゼロではありません。情報処理安全確保支援士として、以下の多層防御(Defense in Depth)を実装しました。

① ネットワーク層:CORSの動的ホワイトリスト化 APIを全公開する(Access-Control-Allow-Origin: *)のは非常に危険です。 本ツールでは、Lambda側でリクエストのOriginヘッダーをチェックし、「本番サイトのドメイン」と「自分のローカル開発環境」のみを許可する動的なホワイトリスト形式を採用しています。これにより、第三者のサイトからの不正なAPI呼び出しを遮断しています。

【🛡️ セキスペの深掘り:localhost許可のジレンマ】 鋭い方は「ローカル開発環境(localhost)を許可すると、他人のlocalhostからもブラウザ経由でAPIを叩けてしまうのでは?」と気づくかもしれません。結論として、その通りです。 しかし、そもそもCORSは「ブラウザのセキュリティ機構」に過ぎず、攻撃者が curl や専用ツールを使えばOriginヘッダーは容易に偽装・無視されます。 そのため、CORSはあくまで「一般サイトへの勝手な埋め込み(タダ乗り)を防ぐ第一関門」として割り切り、真の攻撃や過剰アクセスに対しては、後述する「③ インフラ層のレート制限」で物理的にブロックする、という 役割分担(多層防御) を設計思想としています。

② アプリ層:厳格な入力値検証(バリデーション) ブラウザ側で制限を設けていても、プロキシツール(Burp Suite等)でリクエストを書き換えれば異常な値を送り込むことが可能です。 Lambda側では、文字数が1〜128文字の範囲内であるか等を厳格にチェックし、不正なリクエストは即座に 400 Bad Request を返すように設計しています。

③ インフラ層:Economic DoS(課金)への対策 サーバーレスの懸念点は、大量リクエストによる課金額の増大です。これを防ぐため、API Gatewayのスロットリング機能を設定しました。

レート制限: 5リクエスト/秒

バースト制限: 10リクエスト さらに、Lambdaの「予約済み同時実行数」も最小限に設定することで、万が一の暴走時にも物理的にリソースを制限し、クラウド破産から身を守っています。

  1. おわりに 今回の「俺の道具箱」構築を通じて、Astroの爆速なレスポンスと、AWSサーバーレスの堅牢なセキュリティを両立させる楽しさを再発見しました。

インフラエンジニアの仕事は、往々にして「守り」の業務が多くなりがちですが、こうして自ら「作り、守る」経験を積むことは、技術者としての視座を確実に広げてくれます。

今後は、この基盤を活かして「CIDR計算ツール」など、実務をより楽にする機能を順次追加していく予定です。クラウドとセキュリティを軸にした高度な技術支援を目指し、次はAWS Solutions Architect - Professional (SAP) の取得に向けて歩みを進めていきます。