mcpField
S
static-frontend-hosting

static-frontend-hosting

github.com/loxosceles-devクラウド・DevOps167 回インストール
リポジトリ

static-frontend-hosting について

静的フロントエンドのホスティングと認証を計画するエンジニア向けのリファレンススキルです。S3、CloudFront、Lambda@Edge でログイン画面を使わずトークン認証を行う構成と、リージョン制約やデプロイ手順を解説します。

主な機能

  1. 01S3 による静的ファイルのホスティング
  2. 02CloudFront によるコンテンツ配信
  3. 03Lambda@Edge によるトークン認証
  4. 04Origin Access Control による S3 の保護
  5. 05マルチリージョンデプロイの指針

活用シーン

  1. 01招待制デモアプリのホスティング
  2. 02アクセス制限付きマーケティングコンテンツの配信
  3. 03顧客別ドキュメント表示の提供

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/loxosceles-dev/dev-skills --skill static-frontend-hosting

インストール後、Claude Code で/static-frontend-hostingを入力して読み込まれたか確認します。

詳細

エッジ認証を使用した静的フロントエンドホスティング

これは参考パターンです。 このアプローチを参考にし、状況に合わせて調整してください。そのままコピーしないでください。

課題:ユーザーにログインを求めずに認証を行える、低コストでグローバルに分散されたフロントエンドホスティングが必要です。

解決策:S3 上の静的サイト + CloudFront CDN + 透過的な認証を行う Lambda@Edge。


パターン

アーキテクチャ:

User Request
    ↓
CloudFront (CDN)
    ↓
Lambda@Edge (us-east-1) ← Validates token, sets cookies
    ↓
S3 Bucket (Static Files)

主なコンポーネント:

  • S3 Bucket:静的なフロントエンドのビルド成果物(HTML、JS、CSS)をホストします
  • CloudFront:高速配信を実現するグローバル CDN です
  • Lambda@Edge:リクエストをインターセプトして認証を処理します
  • Origin Access Control:S3 バケットを保護します(アクセスできるのは CloudFront のみです)

このパターンを使う理由

メリット:

  • 低コスト:24 時間稼働するサーバーは不要で、ストレージと帯域幅の料金のみが発生します
  • グローバルなパフォーマンス:世界各地に CloudFront のエッジロケーションがあります
  • スケーラビリティ:トラフィックの急増にも自動で対応します
  • 透過的な認証:ユーザーはログイン画面を使わず、リンク経由で認証されます
  • 静的サイトのセキュリティ:サーバーサイドの脆弱性がなく、静的ファイルのみを使用します

ユースケース:

  • パーソナライズされたアクセスを提供するポートフォリオサイト
  • 招待制アクセスを提供するデモアプリケーション
  • コンテンツへのアクセスを制限するマーケティングサイト
  • 顧客ごとの表示に対応するドキュメント

実装

S3 Bucket:

const websiteBucket = new s3.Bucket(this, 'WebsiteBucket', {
  bucketName: `${PROJECT_ID}-web-${environment}`,
  blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, // Not public!
  removalPolicy: cdk.RemovalPolicy.DESTROY
});

CloudFront Distribution:

const distribution = new cloudfront.Distribution(this, 'Distribution', {
  defaultBehavior: {
    origin: new origins.S3Origin(websiteBucket),
    viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
    edgeLambdas: [{
      functionVersion: authFunction.currentVersion,
      eventType: cloudfront.LambdaEdgeEventType.VIEWER_REQUEST
    }]
  }
});

Lambda@Edge Function:

export async function handler(event) {
  const request = event.Records[0].cf.request;
  const queryParams = new URLSearchParams(request.querystring);
  const token = queryParams.get('token');
  
  if (token) {
    // Validate token (check signature, expiration, etc.)
    const isValid = await validateToken(token);
    
    if (isValid) {
      // Set authentication cookie
      return {
        status: '302',
        headers: {
          'location': [{ value: '/' }],
          'set-cookie': [{ value: `auth_token=${token}; Secure; HttpOnly` }]
        }
      };
    }
  }
  
  // Check existing cookie
  const cookies = request.headers.cookie?.[0]?.value || '';
  if (cookies.includes('auth_token=')) {
    return request; // Authenticated, proceed
  }
  
  // Not authenticated, show public view or error
  return request;
}

重要なトレードオフ:Lambda@Edge のリージョン要件

制約:Lambda@Edge 関数は us-east-1 リージョンにデプロイする必要があります。

理由:CloudFront は us-east-1 から管理されるグローバルサービスです。エッジ関数はこのリージョンからグローバルに複製されます。

影響:

  • Web ホスティング用の CDK スタックは us-east-1 にデプロイする必要があります
  • メインのインフラストラクチャが別のリージョン(例:eu-central-1)にある場合は、スタックを分ける必要があります
  • リージョンをまたぐ参照が複雑になります

回避策:

// Main stack in eu-central-1
const mainStack = new MainStack(app, 'MainStack', {
  env: { region: 'eu-central-1' }
});

// Web stack in us-east-1 (for Lambda@Edge)
const webStack = new WebStack(app, 'WebStack', {
  env: { region: 'us-east-1' }
});

// Pass data via SSM Parameter Store, not direct references

デプロイパイプライン

ビルドプロセス:

  1. 静的フロントエンドをビルドします(npm run build)
  2. インフラストラクチャ(S3、CloudFront、Lambda@Edge)をデプロイします
  3. 静的ファイルを S3 にアップロードします
  4. CloudFront のキャッシュを無効化します

例:

# buildspec.yml
phases:
  build:
    commands:
      - cd frontend && npm run build
      - cd infrastructure && cdk deploy WebStack
      - aws s3 sync frontend/out s3://${BUCKET_NAME}
      - aws cloudfront create-invalidation --distribution-id ${DIST_ID} --paths "/*"

使用しないケース

  • サーバーサイドレンダリング:代わりに ECS/Lambda と API Gateway を使用します
  • リアルタイム更新:Lambda と WebSocket API を使用します
  • 複雑な認証フロー:Cognito Hosted UI またはカスタム認証サービスを使用します
  • 頻繁なコンテンツ更新:インクリメンタル静的再生成または動的レンダリングを検討します

関連パターン


段階的な改善

このスキルで防止できるはずの動作について開発者から修正を受けた場合は、同じ修正を今後防げるよう、このスキルに加える具体的な修正案を提案してください。

コメント