VercelのOIDC認証付きバックエンドサーバーAWS EC2のセットアップ

概要

このガイドでは、Vercel OIDCを使用してAWS上にバックエンドサーバーをセットアップし、ローカルからEC2上のAPI接続テストを実施する手順を説明します。


前提条件

  • AWSアカウント

  • Vercelアカウント

  • Node.js(バージョン18.x以上推奨)

  • npm or yarn

  • EC2インスタンス(Ubuntu推奨)

  • EC2上にセットアップしたAPIはOIDC経由ではない状態で正常に動作

セットアップ手順

1. VercelアカウントでのOIDC設定を有効にする

  • Vercelダッシュボードからプロジェクトを開く

  • 設定タブを選択します

  • セキュリティセクションで、OIDCフェデレーションによるバックエンドアクセスのセキュリティを有効にする

参考リンク:https://vercel.com/docs/security/secure-backend-access/oidc

2. AWS IAMロールの設定

  1. AWSコンソールでIAMに移動

  2. 新しいロールを作成(例:vercel-oidc-test-240925)

  3. 信頼関係を以下のように設定:

    1. OIDC IDプロバイダーを作成する

      1. AWSコンソールに移動する

      2. IAMに移動し、次にアイデンティティプロバイダに移動します

      3. プロバイダーの追加を選択

      4. プロバイダータイプからOpenID Connectを選択します

      5. プロバイダーURLフィールドhttps://oidc.vercel.comに入力します

      6. オーディエンスhttps://vercel.com/[TEAM_SLUG]フィールドに、VercelチームのURLのパスを置き換えて入力します。[TEAM_SLUG]

      7. プロバイダーの追加を選択

    2. IAMロールを作成する

    3. 必要な権限ポリシーをアタッチ(例:AdministratorAccess)

  4. ロールを作成したら、ロールの ARNをコピーし、キー名を使用して Vercel プロジェクトで"AWS_ROLE_ARN"環境変数として宣言します

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::[your account number]:oidc-provider/oidc.vercel.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.vercel.com:aud": "https://vercel.com/test-46f30ef0"
                },
                "StringLike": {
                    "oidc.vercel.com:sub": [
                        "owner:test-46f30ef0:project:*:environment:preview",
                        "owner:test-46f30ef0:project:*:environment:production",
                        "owner:test-46f30ef0:project:*:environment:development"
                    ]
                }
            }
        }
    ]
}

AWS_ROLE_ARN=arn:aws:iam::accountid:user/username

2. EC2インスタンスのセットアップ

  1. EC2インスタンスを起動(Ubuntu推奨)

  2. SSHでインスタンスに接続

3. 環境変数の設定

EC2インスタンスで以下のコマンドを実行:

echo 'export AWS_REGION="ap-south-1"' >> ~/.bashrc
echo 'export AWS_ROLE_ARN="arn:aws:iam::[account number]:role/vercel-oidc-test-240925"' >> ~/.bashrc
echo 'export PORT="3000"' >> ~/.bashrc
echo 'export VERCEL_OIDC_TOKEN="teamtoken"' >> ~/.bashrc
echo 'export VERCEL_PROJECT_ID="projectid"' >> ~/.bashrc
source ~/.bashrc

4. Node.jsとnpmのインストール

sudo apt update
sudo apt install nodejs npm

5. プロジェクトのセットアップ

  1. プロジェクトディレクトリを作成し、移動

6. サーバーコードの作成

`server.js`ファイルを作成し、必要なコードを記述。以下は一例。

const express = require('express');
const mongoose = require('mongoose');
const { PORT, MONGODB_URI } = require('./src/config');
const cors = require('cors');
const app = express();
const { STSClient, AssumeRoleWithWebIdentityCommand } = require("@aws-sdk/client-sts");

// CORS設定
app.use(cors({
  origin: [
    'https://xxxxx.vercel.app',
  ],
  credentials: true
}));

app.use(express.json());

// デバッグミドルウェア
app.use((req, res, next) => {
  console.log('Received request with headers:', req.headers);
  console.log('Authorization header:', req.headers.authorization);
  next();
});

// 認証ミドルウェア
async function validateVercelOIDCToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  if (!authHeader) {
    return res.status(401).json({ error: "No authorization header provided" });
  }

  const token = authHeader.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: "No token provided" });
  }

  try {
    console.log('Attempting to assume role with token');
    console.log('AWS_REGION:', process.env.AWS_REGION);
    console.log('AWS_ROLE_ARN:', process.env.AWS_ROLE_ARN);

    const sts = new STSClient({ region: process.env.AWS_REGION });
    const command = new AssumeRoleWithWebIdentityCommand({
      RoleArn: process.env.AWS_ROLE_ARN,
      RoleSessionName: 'VercelSession',
      WebIdentityToken: token
    });

    const result = await sts.send(command);
    console.log('Successfully assumed role:', result);
    next();
  } catch (error) {
    console.error("Error assuming role:", error);
    res.status(401).json({ error: "Invalid Vercel OIDC token", details: error.message });
  }
}

mongoose.connect(MONGODB_URI, {})
  .then(() => console.log('Connected to MongoDB'))
  .catch(err => {
    console.error('MongoDB connection error:', err);
    process.exit(1);
  });

// activeAPIの使用
app.use('/api/active', validateVercelOIDCToken, activeRoutes);

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
});

app.listen(PORT, '0.0.0.0', () => {
  console.log(`Server is running on port ${PORT}`);
});

7. Vercel CLIでローカルへVERCEL_OIDC_TOKENをダウンロード

ダウンロードされた.env.localへ対象となるその他の環境変数が書き込まれる。環境変数としてセット。

npm i -g vercel
vercel env pull
vercel link
echo 'export VERCEL_OIDC_TOKEN="XXXXXX"' >> ~/.bashrc
source ~/.bashrc

8.ローカルでEC2上のAPIとの接続テスト

以下はテストスクリプト例

if [ -z "$VERCEL_OIDC_TOKEN" ]; then
    echo "Error: VERCEL_OIDC_TOKEN is not set."
    exit 1
fi

echo "Sending request with VERCEL_OIDC_TOKEN..."
curl -v -H 'Authorization: Bearer '"$VERCEL_OIDC_TOKEN"'' \
    "https://XXXX.com/api/active/check/0x1234567890123456789012345678901234567890"

echo -e "\n\nSending request without token for comparison..."
curl -v "https://XXXX.com/api/active/check/0x1234567890123456789012345678901234567890"

いいなと思ったら応援しよう!