{"id":46539117,"url":"https://github.com/oharu121/connect-pomerium","last_synced_at":"2026-03-07T00:31:10.334Z","repository":{"id":325641859,"uuid":"1101469431","full_name":"oharu121/connect-pomerium","owner":"oharu121","description":"Automate Pomerium tunnel creation for testing, CI/CD, and automation","archived":false,"fork":false,"pushed_at":"2026-02-27T03:59:28.000Z","size":33574,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-27T10:39:21.536Z","etag":null,"topics":["authentication","automation","pomerium","proxy","sso","tunnel"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/connect-pomerium","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oharu121.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-21T18:06:37.000Z","updated_at":"2026-02-27T03:59:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/oharu121/connect-pomerium","commit_stats":null,"previous_names":["oharu121/connect-pomerium"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/oharu121/connect-pomerium","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oharu121%2Fconnect-pomerium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oharu121%2Fconnect-pomerium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oharu121%2Fconnect-pomerium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oharu121%2Fconnect-pomerium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oharu121","download_url":"https://codeload.github.com/oharu121/connect-pomerium/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oharu121%2Fconnect-pomerium/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30204154,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"ssl_error","status_checked_at":"2026-03-06T18:57:34.882Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","automation","pomerium","proxy","sso","tunnel"],"created_at":"2026-03-07T00:31:07.846Z","updated_at":"2026-03-07T00:31:10.310Z","avatar_url":"https://github.com/oharu121.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# connect-pomerium\n\n[![npm version](https://badge.fury.io/js/connect-pomerium.svg)](https://badge.fury.io/js/connect-pomerium)\n![License](https://img.shields.io/npm/l/connect-pomerium)\n![Types](https://img.shields.io/npm/types/connect-pomerium)\n![NPM Downloads](https://img.shields.io/npm/dw/connect-pomerium)\n\n\u003e Automate Pomerium tunnel creation for testing, CI/CD, and automation\n\n`connect-pomerium` is a lightweight TypeScript/JavaScript library that simplifies the creation and management of [Pomerium](https://www.pomerium.com/) tunnels. It's designed specifically for **automation scenarios** where you need programmatic access to Pomerium-protected services without manual browser interaction.\n\n## Requirements\n\n- **Node.js** 20.0.0 or higher\n- **Pomerium CLI** v0.29.0 or later ([Download](https://github.com/pomerium/cli/releases))\n\n\u003e **Note:** This library requires pomerium-cli v0.29.0+ which uses JSON logging. If you're using an older CLI version, please use `connect-pomerium@1.x` instead.\n\n## Features\n\n- 🚀 **Zero runtime dependencies** - Lean and fast\n- 🔐 **Flexible authentication** - Manual browser auth or automated (Playwright, Puppeteer, etc.)\n- 🔄 **Auto-reconnect support** - Configurable reconnection for long-running processes\n- 🎯 **TypeScript-first** - Full type safety and IntelliSense support\n- 🖥️ **Cross-platform** - Works on Windows, macOS (Intel \u0026 ARM), and Linux\n- 📦 **Bundled binaries** - Pomerium CLI included, no external dependencies\n- 🎨 **Lifecycle hooks** - Monitor connection state with callbacks\n- ⚡ **Simple API** - Get started with just 3 lines of code\n\n## Installation\n\n```bash\npnpm add connect-pomerium\n```\n\n## Quick Start\n\n### Basic Usage (Manual Auth)\n\n```typescript\nimport { PomeriumTunnel } from 'connect-pomerium';\n\nconst tunnel = new PomeriumTunnel({\n  targetHost: 'tcp+https://db.corp.pomerium.io:5432',\n  listenPort: 5432,\n});\n\nawait tunnel.start(); // Browser opens for auth\nconsole.log('Connected! Access your service at localhost:5432');\n\n// Your automation code here...\n\nawait tunnel.stop();\n```\n\n### Automated Auth (Playwright Example)\n\n```typescript\nimport { chromium } from 'playwright';\nimport { PomeriumTunnel } from 'connect-pomerium';\n\nconst tunnel = new PomeriumTunnel({\n  targetHost: 'tcp+https://api.corp.pomerium.io:443',\n  listenPort: 8443,\n\n  onAuthRequired: async (authUrl) =\u003e {\n    const browser = await chromium.launch({ headless: true });\n    const page = await browser.newPage();\n\n    await page.goto(authUrl);\n    await page.fill('#username', process.env.USERNAME!);\n    await page.fill('#password', process.env.PASSWORD!);\n    await page.click('button[type=\"submit\"]');\n\n    await browser.close();\n  },\n});\n\nawait tunnel.start(); // No browser popup, fully automated\n```\n\n## Configuration Options\n\n```typescript\ninterface PomeriumTunnelConfig {\n  // Required\n  targetHost: string;           // Pomerium target (e.g., 'tcp+https://host:port')\n  listenPort: number;            // Local port to listen on\n\n  // Optional\n  cliPath?: string;              // Custom path to Pomerium CLI binary\n  onAuthRequired?: (url: string) =\u003e Promise\u003cvoid\u003e; // Auth handler\n  autoReconnect?: boolean;       // Enable auto-reconnect (default: false)\n  maxReconnectAttempts?: number; // Max reconnection attempts (default: 0 = infinite)\n  reconnectDelay?: number;       // Delay between retries in ms (default: 5000)\n  connectionTimeout?: number;    // Connection timeout in ms (default: 60000)\n\n  // Lifecycle hooks\n  onConnected?: () =\u003e void;\n  onDisconnected?: () =\u003e void;\n  onReconnecting?: (attempt: number) =\u003e void;\n  onReconnectFailed?: () =\u003e void;\n  onError?: (error: Error) =\u003e void;\n\n  // NEW in v2.0.0\n  onLog?: (log: PomeriumLogEntry) =\u003e void;  // Access raw CLI logs\n  logLevel?: 'debug' | 'info' | 'warn' | 'error'; // CLI log level (default: 'info')\n  debug?: boolean;                           // Enable stderr logging (default: false)\n}\n```\n\n## API Reference\n\n### `PomeriumTunnel`\n\n#### `constructor(config: PomeriumTunnelConfig)`\n\nCreates a new tunnel instance with the specified configuration.\n\n#### `async start(): Promise\u003cvoid\u003e`\n\nStarts the tunnel and waits for connection establishment. If `onAuthRequired` is provided, the browser will be suppressed and your callback will handle authentication. Otherwise, Pomerium will open the browser for manual login.\n\n**Throws:**\n- `ConnectionTimeoutError` - If connection times out\n- `ProcessStartError` - If the Pomerium process fails to start\n- `ProcessExitError` - If the process exits unexpectedly\n\n#### `async stop(): Promise\u003cvoid\u003e`\n\nStops the tunnel and cleans up resources.\n\n#### `getState(): TunnelState`\n\nReturns the current tunnel state.\n\n```typescript\ninterface TunnelState {\n  connected: boolean;\n  reconnecting: boolean;\n  reconnectAttempts: number;\n}\n```\n\n#### `isConnected(): boolean`\n\nReturns `true` if the tunnel is currently connected.\n\n## Examples\n\nThe `examples/` directory contains complete working examples:\n\n1. **[01-basic-manual-auth.ts](examples/01-basic-manual-auth.ts)** - Simple usage with manual browser authentication\n2. **[02-okta-playwright.ts](examples/02-okta-playwright.ts)** - Automated Okta login using Playwright\n3. **[03-google-puppeteer.ts](examples/03-google-puppeteer.ts)** - Automated Google SSO using Puppeteer\n4. **[04-ci-cd-auto-reconnect.ts](examples/04-ci-cd-auto-reconnect.ts)** - CI/CD usage with auto-reconnect\n\nTo run an example:\n\n```bash\n# Install dependencies for the example\npnpm add playwright  # or puppeteer\n\n# Run the example\nnpx tsx examples/02-okta-playwright.ts\n```\n\n## Use Cases\n\n### CI/CD Pipelines\n\nRun integration tests against Pomerium-protected services:\n\n```typescript\nconst tunnel = new PomeriumTunnel({\n  targetHost: 'tcp+https://staging-api.corp.pomerium.io:443',\n  listenPort: 8443,\n  autoReconnect: true,\n  maxReconnectAttempts: 5,\n  onAuthRequired: async (url) =\u003e {\n    // Use service account credentials\n    await automateLogin(url);\n  },\n});\n\nawait tunnel.start();\nawait runIntegrationTests();\nawait tunnel.stop();\n```\n\n### Local Development\n\nAccess remote databases or services during development:\n\n```typescript\nconst tunnel = new PomeriumTunnel({\n  targetHost: 'tcp+https://prod-db.corp.pomerium.io:5432',\n  listenPort: 5432,\n});\n\nawait tunnel.start(); // Manual auth in browser\n// Now connect to localhost:5432 with your database client\n```\n\n### Automated Scripts\n\nBuild automation tools that interact with protected services:\n\n```typescript\nconst tunnel = new PomeriumTunnel({\n  targetHost: 'tcp+https://admin-api.corp.pomerium.io:443',\n  listenPort: 8443,\n  onAuthRequired: automateAuth,\n});\n\nawait tunnel.start();\nawait performAdminTasks();\nawait tunnel.stop();\n```\n\n## Authentication\n\n### Manual Authentication (Default)\n\nIf you don't provide `onAuthRequired`, Pomerium will open your default browser for authentication. This is the simplest approach for local development.\n\n### Automated Authentication\n\nFor CI/CD and automation, provide an `onAuthRequired` callback. The library supports any browser automation tool:\n\n#### With Playwright\n\n```bash\npnpm add playwright\n```\n\n```typescript\nonAuthRequired: async (authUrl) =\u003e {\n  const browser = await chromium.launch({ headless: true });\n  const page = await browser.newPage();\n  await page.goto(authUrl);\n  // Your auth logic...\n  await browser.close();\n}\n```\n\n#### With Puppeteer\n\n```bash\npnpm add puppeteer\n```\n\n```typescript\nonAuthRequired: async (authUrl) =\u003e {\n  const browser = await puppeteer.launch({ headless: true });\n  const page = await browser.newPage();\n  await page.goto(authUrl);\n  // Your auth logic...\n  await browser.close();\n}\n```\n\n#### With Any Other Tool\n\nThe callback just needs to handle the authentication flow. You can use any tool that can interact with web pages.\n\n## Auto-Reconnect\n\nBy default, auto-reconnect is **disabled** (`autoReconnect: false`). This is intentional for automation scenarios where you want explicit control over failures.\n\nTo enable auto-reconnect:\n\n```typescript\nconst tunnel = new PomeriumTunnel({\n  targetHost: 'tcp+https://api.corp.pomerium.io:443',\n  listenPort: 8443,\n  autoReconnect: true,\n  maxReconnectAttempts: 3,  // 0 = infinite\n  reconnectDelay: 5000,      // 5 seconds between attempts\n\n  onReconnecting: (attempt) =\u003e {\n    console.log(`Reconnecting (${attempt}/3)...`);\n  },\n\n  onReconnectFailed: () =\u003e {\n    console.error('Failed to reconnect');\n    process.exit(1);\n  },\n});\n```\n\n## Advanced Features (v2.0.0+)\n\n### Debug Logging\n\nControl the verbosity of pomerium-cli logs:\n\n```typescript\nconst tunnel = new PomeriumTunnel({\n  targetHost: 'tcp+https://example.com:443',\n  listenPort: 8443,\n  logLevel: 'debug', // Options: 'debug', 'info', 'warn', 'error'\n});\n```\n\n### Access Raw Logs\n\nGet access to structured log entries from pomerium-cli:\n\n```typescript\nconst tunnel = new PomeriumTunnel({\n  targetHost: 'tcp+https://example.com:443',\n  listenPort: 8443,\n  onLog: (log) =\u003e {\n    // Log is a structured object with: level, message, component, etc.\n    console.log(`[${log.level.toUpperCase()}] ${log.message}`);\n\n    // Access additional fields\n    if (log.component) console.log(`  Component: ${log.component}`);\n    if (log.error) console.error(`  Error: ${log.error}`);\n    if (log['auth-url']) console.log(`  Auth URL: ${log['auth-url']}`);\n  },\n});\n```\n\n### Parse Logs Manually\n\nYou can also parse pomerium-cli logs yourself:\n\n```typescript\nimport { parsePomeriumLog, extractAuthUrl, type PomeriumLogEntry } from 'connect-pomerium';\n\n// Parse JSON log line\nconst logEntry = parsePomeriumLog('{\"level\":\"info\",\"message\":\"connected\"}');\nif (logEntry) {\n  console.log(logEntry.level, logEntry.message);\n}\n\n// Extract auth URL from plain text\nconst url = extractAuthUrl('Your browser has been opened to visit:\\n\\nhttps://auth.example.com\\n');\nconsole.log(url); // \"https://auth.example.com\"\n```\n\n## Troubleshooting\n\n### Version Compatibility\n\nIf you see log parsing errors or connection issues:\n\n1. **Check your pomerium-cli version:**\n   ```bash\n   pomerium-cli --version\n   ```\n\n2. **If \u003c v0.29.0:**\n   - Update to v0.29.0+ from https://github.com/pomerium/cli/releases\n   - OR use `connect-pomerium@1.x`: `pnpm add connect-pomerium@1.0.1`\n\n3. **If already v0.29.0+** and still having issues, please [open an issue](https://github.com/oharu121/connect-pomerium/issues)\n\n### Binary Not Found\n\nIf you see `BinaryNotFoundError`, the Pomerium CLI binary might not be accessible. You can provide a custom path:\n\n```typescript\nconst tunnel = new PomeriumTunnel({\n  targetHost: '...',\n  listenPort: 8443,\n  cliPath: '/custom/path/to/pomerium-cli',\n});\n```\n\n### Connection Timeout\n\nIf connections timeout frequently, increase the timeout:\n\n```typescript\nconst tunnel = new PomeriumTunnel({\n  targetHost: '...',\n  listenPort: 8443,\n  connectionTimeout: 120000, // 2 minutes\n});\n```\n\n### Authentication Fails\n\nIf automated authentication fails:\n1. Check your credentials are correct\n2. Verify the auth flow by running with manual auth first\n3. Add error handling in your `onAuthRequired` callback\n4. Check Pomerium CLI logs (they're output to console by default)\n\n### macOS Quarantine\n\nOn macOS, if the binary is quarantined by Gatekeeper, the library automatically removes the quarantine attribute. If you still have issues, manually run:\n\n```bash\nxattr -d com.apple.quarantine bin/pomerium-cli-darwin-*\n```\n\n## Platform Support\n\n| Platform | Architecture | Binary Included |\n|----------|-------------|-----------------|\n| Windows  | x64         | ✅              |\n| macOS    | x64 (Intel) | ✅              |\n| macOS    | arm64 (M1+) | ✅              |\n| Linux    | x64         | ✅              |\n\n## TypeScript Support\n\nThis library is written in TypeScript and provides full type definitions. All configuration options, methods, and errors are fully typed.\n\n```typescript\nimport type { PomeriumTunnelConfig, TunnelState } from 'connect-pomerium';\n```\n\n## Error Handling\n\nThe library exports custom error classes for different failure scenarios:\n\n```typescript\nimport {\n  PomeriumError,           // Base error class\n  ConnectionTimeoutError,  // Connection establishment timeout\n  BinaryNotFoundError,     // Pomerium CLI binary not found\n  ProcessExitError,        // Process exited unexpectedly\n  ProcessStartError,       // Failed to start process\n  AuthenticationError,     // Authentication callback failed\n} from 'connect-pomerium';\n\ntry {\n  await tunnel.start();\n} catch (error) {\n  if (error instanceof ConnectionTimeoutError) {\n    console.error('Connection timed out');\n  } else if (error instanceof AuthenticationError) {\n    console.error('Auth failed');\n  }\n}\n```\n\n## FAQ\n\n### Why no Playwright/Puppeteer dependency?\n\nWe keep the library dependency-free so you can choose your own browser automation tool (or none at all). This keeps the package size small (~10MB with binaries) instead of bloated (~200MB with Playwright).\n\n### Should I use auto-reconnect?\n\n**For CI/CD**: Usually no. You want explicit failures so you can debug issues.\n**For long-running processes**: Yes. Enable it with reasonable retry limits.\n**For local development**: Depends on your workflow.\n\n### Can I create multiple tunnels?\n\nYes! Create multiple `PomeriumTunnel` instances with different ports:\n\n```typescript\nconst dbTunnel = new PomeriumTunnel({ targetHost: '...', listenPort: 5432 });\nconst apiTunnel = new PomeriumTunnel({ targetHost: '...', listenPort: 8443 });\n\nawait Promise.all([dbTunnel.start(), apiTunnel.start()]);\n```\n\n### Is this a replacement for Pomerium?\n\nNo. This library is specifically for **automation scenarios** (testing, CI/CD, scripts). For production Pomerium deployments, use the official Pomerium installation methods.\n\n## Development\n\n### Build\n\n```bash\npnpm run build\n```\n\n### Test\n\n```bash\npnpm test\n```\n\n### Lint\n\n```bash\npnpm run lint\npnpm run format\n```\n\n### Validate Package Exports\n\n```bash\npnpm run check:exports\n```\n\n## Release Workflow\n\nThis package uses automated publishing via GitHub Actions.\n\n### Creating a Release\n\n1. **Make your changes** and commit them\n2. **Update the version:**\n   ```bash\n   pnpm version patch  # for bug fixes\n   pnpm version minor  # for new features\n   pnpm version major  # for breaking changes\n   ```\n3. **Push the changes and tags:**\n   ```bash\n   git push \u0026\u0026 git push --tags\n   ```\n4. **Package automatically publishes to npm** 🎉\n\n## License\n\nMIT © oharu121\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## Issues\n\nIf you encounter any issues, please report them at [GitHub Issues](https://github.com/oharu121/connect-pomerium/issues).\n\n## Support\n\n- **Issues**: [GitHub Issues](https://github.com/oharu121/connect-pomerium/issues)\n- **Pomerium Docs**: [pomerium.com/docs](https://www.pomerium.com/docs/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foharu121%2Fconnect-pomerium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foharu121%2Fconnect-pomerium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foharu121%2Fconnect-pomerium/lists"}