1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Playwright + TOTPでPomerium + Okta認証を自動化してみた

Last updated at Posted at 2025-05-22

はじめに

社内環境にアクセスするためのJump Serverに、Pomeriumゲートウェイ+Okta認証を通して接続する必要があり、毎回の手動認証に手間を感じていました。

そこで、Playwright + TOTP(Time-based One-Time Passwordを用いて、OktaのMFA認証を自動化し、Pomerium経由のTCP接続を自動起動する仕組みを構築したので紹介します。

解決したかった課題

  • Pomeriumを起動すると、Oktaログイン→MFA認証→トンネル確立の流れが手動
  • 特に毎回手でOkta Verifyコードを入力するのが面倒
  • 開発/運用チームのメンバーも手動対応しており、属人化していた

技術スタック

  • Playwright: ブラウザ自動操作(Oktaログイン処理)
  • otplib: TOTPコード生成(Okta Verifyコード自動入力)
  • child_process.spawn: Pomeriumバイナリの起動
  • chromium (via Playwright): headlessブラウザ操作
  • Node.js (TypeScript)

処理フローの全体像

  1. Node.jsからPomeriumバイナリをspawn
  2. stderrから認証URLを取得
  3. PlaywrightでそのURLにアクセス
  4. ユーザー名+パスワードを入力してログイン
  5. Okta Verifyに切り替え、TOTPコードを自動入力
  6. 認証完了でPomeriumがトンネルを確立

コード解説

1️⃣ Pomerium起動とURLの取得

public initPomerium(): Promise<void> {
  const pomeriumProcess = spawn(pomeriumPath, [
    "tcp", pomeriumHost,
    "--listen", `:${pomeriumPort}`,
  ]);

  pomeriumProcess.stderr.on("data", async (chunk) => {
    const message = chunk.toString();

    if (message.includes("listening on")) {
      Logger.success(`Pomerium is ready on port ${pomeriumPort}`);
      resolve();
    } else if (message.includes("https")) {
      const match = message.match(/https?:\/\/[^\s]+/g);
      if (match) {
        await Playwright.loginPomerium(match[0]);
      }
    } else {
      reject(new Error(`Failed to start Pomerium: ${message}`));
    }
  });
}
  • stderrからhttps://で始まるURLを抽出 → Pomeriumのログインページ
  • Macではchmodxattrで初回実行制限を解除しているのもポイント

2️⃣ PlaywrightによるOktaログイン自動化

public async loginPomerium(url: string) {
  const browser = await chromium.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto(url);

  await page.getByRole("textbox", { name: "Username" }).fill(credentials.SSH_USERNAME);
  await page.getByRole("textbox", { name: "Password" }).fill(credentials.JUMP_SERVER_PASSWORD);
  await page.getByRole("button", { name: "Sign in" }).click();

  await page.getByRole("link", { name: "Select to enter a code from" }).click();

  const otpInput = await page.getByRole("textbox", { name: "Enter code from Okta Verify" });
  const mfaOtp = Okta.generateOTP();  // otplibなどを使って生成
  await otpInput.fill(mfaOtp);
  await page.getByRole("button", { name: "Verify" }).click();
}
  • ログインページ→Okta Verifyへの遷移→TOTP入力→認証完了の流れを再現
  • Okta.generateOTP()otplib 等で事前に設定されたシークレットから生成できます
import { totp } from "otplib";

export const Okta = {
  generateOTP(): string {
    return totp.generate(process.env.OKTA_MFA_SECRET || "");
  }
};

TOTPのセットアップはこちら:

成果と今後の展望

  • Oktaログイン~MFA認証の自動化で、Pomeriumトンネル確立を完全自動化
  • 毎回の認証手間がゼロに。10秒以内にSSHが使える状態に!
  • 今後はGitHub Actionsなどから自動でVPN経由ジョブを走らせる応用も検討

PomeriumやOktaの認証処理が面倒…という方は、Playwright+TOTPによる自動化をぜひ試してみてください!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?