mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 14:15:24 +00:00
feat: move opkssh and warpgate into plugins (C3)
This commit is contained in:
1 parent
925da4a661
commit
98d367d7e2
336 files changed
+22380
-4746
No files matched your search
@@ -78,7 +78,7 @@
|
||||
"containerMustBeRunning": "Container must be running to access console",
|
||||
"verificationCodePrompt": "Enter verification code",
|
||||
"totpVerificationFailed": "TOTP verification failed. Please try again.",
|
||||
"warpgateVerificationFailed": "Warpgate authentication failed. Please try again.",
|
||||
"browserSignInFailed": "Sign-in failed. Please try again.",
|
||||
"connectedTo": "Connected to {{containerName}}",
|
||||
"disconnected": "Disconnected",
|
||||
"consoleError": "Console error",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Die houer moet loop om toegang tot die konsole te verkry",
|
||||
"verificationCodePrompt": "Voer verifikasiekode in",
|
||||
"totpVerificationFailed": "TOTP-verifikasie het misluk. Probeer asseblief weer.",
|
||||
"warpgateVerificationFailed": "Warpgate-verifikasie het misluk. Probeer asseblief weer.",
|
||||
"connectedTo": "Gekoppel aan {{containerName}}",
|
||||
"disconnected": "Ontkoppel",
|
||||
"consoleError": "Konsolefout",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "يجب أن تكون الحاوية قيد التشغيل للوصول إلى وحدة التحكم",
|
||||
"verificationCodePrompt": "أدخل رمز التحقق",
|
||||
"totpVerificationFailed": "فشل التحقق من TOTP. يرجى المحاولة مرة أخرى.",
|
||||
"warpgateVerificationFailed": "فشلت مصادقة Warpgate. يرجى المحاولة مرة أخرى.",
|
||||
"connectedTo": "متصل بـ {{containerName}}",
|
||||
"disconnected": "تم قطع الاتصال",
|
||||
"consoleError": "خطأ في وحدة التحكم",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Контейнерът трябва да е работещ, за да има достъп до конзолата",
|
||||
"verificationCodePrompt": "Въведете код за потвърждение",
|
||||
"totpVerificationFailed": "Проверката на TOTP не бе успешна. Моля, опитайте отново.",
|
||||
"warpgateVerificationFailed": "Удостоверяването на Warpgate не бе успешно. Моля, опитайте отново.",
|
||||
"connectedTo": "Свързано с {{containerName}}",
|
||||
"disconnected": "Изключен",
|
||||
"consoleError": "Грешка в конзолата",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "কনসোল অ্যাক্সেস করতে হলে কন্টেইনারটি অবশ্যই চালু থাকতে হবে।",
|
||||
"verificationCodePrompt": "যাচাইকরণ কোড প্রবেশ করান",
|
||||
"totpVerificationFailed": "TOTP যাচাইকরণ ব্যর্থ হয়েছে। অনুগ্রহ করে আবার চেষ্টা করুন।",
|
||||
"warpgateVerificationFailed": "ওয়ার্পগেট প্রমাণীকরণ ব্যর্থ হয়েছে। অনুগ্রহ করে আবার চেষ্টা করুন।",
|
||||
"connectedTo": "{{containerName}} এর সাথে সংযুক্ত",
|
||||
"disconnected": "বিচ্ছিন্ন",
|
||||
"consoleError": "কনসোল ত্রুটি",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "El contenidor ha d'estar en execució per accedir a la consola.",
|
||||
"verificationCodePrompt": "Introduïu el codi de verificació",
|
||||
"totpVerificationFailed": "La verificació TOTP ha fallat. Torna-ho a provar.",
|
||||
"warpgateVerificationFailed": "L'autenticació de Warpgate ha fallat. Torna-ho a intentar.",
|
||||
"connectedTo": "Connectat a {{containerName}}",
|
||||
"disconnected": "Desconnectat",
|
||||
"consoleError": "Error de consola",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Pro přístup ke konzoli musí být kontejner spuštěný.",
|
||||
"verificationCodePrompt": "Zadejte ověřovací kód",
|
||||
"totpVerificationFailed": "Ověření TOTP se nezdařilo. Zkuste to prosím znovu.",
|
||||
"warpgateVerificationFailed": "Ověření Warpgate se nezdařilo. Zkuste to prosím znovu.",
|
||||
"connectedTo": "Připojeno k {{containerName}}",
|
||||
"disconnected": "Odpojeno",
|
||||
"consoleError": "Chyba konzole",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Containeren skal køre for at få adgang til konsollen",
|
||||
"verificationCodePrompt": "Indtast bekræftelseskode",
|
||||
"totpVerificationFailed": "TOTP-bekræftelse mislykkedes. Prøv igen.",
|
||||
"warpgateVerificationFailed": "Warpgate-godkendelse mislykkedes. Prøv igen.",
|
||||
"connectedTo": "Forbundet til {{containerName}}",
|
||||
"disconnected": "Afbrudt",
|
||||
"consoleError": "Konsolfejl",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Der Container muss ausgeführt werden, um auf die Konsole zuzugreifen",
|
||||
"verificationCodePrompt": "Bestätigungscode eingeben",
|
||||
"totpVerificationFailed": "TOTP-Überprüfung fehlgeschlagen. Bitte versuchen Sie es erneut.",
|
||||
"warpgateVerificationFailed": "Warpgate-Authentifizierung fehlgeschlagen. Bitte versuchen Sie es erneut.",
|
||||
"connectedTo": "Verbunden mit {{containerName}}",
|
||||
"disconnected": "Getrennt",
|
||||
"consoleError": "Konsolenfehler",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Το κοντέινερ πρέπει να εκτελείται για πρόσβαση στην κονσόλα",
|
||||
"verificationCodePrompt": "Εισαγάγετε τον κωδικό επαλήθευσης",
|
||||
"totpVerificationFailed": "Η επαλήθευση TOTP απέτυχε. Δοκιμάστε ξανά.",
|
||||
"warpgateVerificationFailed": "Ο έλεγχος ταυτότητας Warpgate απέτυχε. Δοκιμάστε ξανά.",
|
||||
"connectedTo": "Συνδεδεμένο με {{containerName}}",
|
||||
"disconnected": "Ασύνδετος",
|
||||
"consoleError": "Σφάλμα κονσόλας",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "El contenedor debe estar en ejecución para acceder a la consola",
|
||||
"verificationCodePrompt": "Introduzca el código de verificación",
|
||||
"totpVerificationFailed": "La verificación TOTP falló. Inténtelo de nuevo.",
|
||||
"warpgateVerificationFailed": "La autenticación Warpgate falló. Inténtelo de nuevo.",
|
||||
"connectedTo": "Conectado a {{containerName}}",
|
||||
"disconnected": "Desconectado",
|
||||
"consoleError": "Error de consola",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Kontin on oltava käynnissä, jotta konsoliin pääsee käsiksi.",
|
||||
"verificationCodePrompt": "Syötä vahvistuskoodi",
|
||||
"totpVerificationFailed": "TOTP-vahvistus epäonnistui. Yritä uudelleen.",
|
||||
"warpgateVerificationFailed": "Warpgate-todennus epäonnistui. Yritä uudelleen.",
|
||||
"connectedTo": "Yhdistetty kohteeseen {{containerName}}",
|
||||
"disconnected": "Yhteys katkennut",
|
||||
"consoleError": "Konsolivirhe",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Le conteneur doit être en cours d'exécution pour accéder à la console",
|
||||
"verificationCodePrompt": "Saisissez le code de vérification",
|
||||
"totpVerificationFailed": "La vérification TOTP a échoué. Veuillez réessayer.",
|
||||
"warpgateVerificationFailed": "L'authentification Warpgate a échoué. Veuillez réessayer.",
|
||||
"connectedTo": "Connecté à {{containerName}}",
|
||||
"disconnected": "Déconnecté",
|
||||
"consoleError": "Erreur de la console",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "יש לפעול על מנת לגשת למסוף.",
|
||||
"verificationCodePrompt": "הזן קוד אימות",
|
||||
"totpVerificationFailed": "אימות TOTP נכשל. אנא נסה שוב.",
|
||||
"warpgateVerificationFailed": "אימות Warpgate נכשל. אנא נסה שוב.",
|
||||
"connectedTo": "מחובר אל {{containerName}}",
|
||||
"disconnected": "מְנוּתָק",
|
||||
"consoleError": "שגיאת קונסולה",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "कंसोल तक पहुंचने के लिए कंटेनर चालू होना चाहिए",
|
||||
"verificationCodePrompt": "सत्यापन कोड दर्ज करें",
|
||||
"totpVerificationFailed": "TOTP सत्यापन विफल। कृपया पुनः प्रयास करें।",
|
||||
"warpgateVerificationFailed": "Warpgate प्रमाणीकरण विफल। कृपया पुनः प्रयास करें।",
|
||||
"connectedTo": "{{containerName}} से जुड़ा",
|
||||
"disconnected": "डिस्कनेक्टेड",
|
||||
"consoleError": "कंसोल त्रुटि",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "A konténernek futnia kell a konzol eléréséhez",
|
||||
"verificationCodePrompt": "Írja be az ellenőrző kódot",
|
||||
"totpVerificationFailed": "A TOTP ellenőrzése sikertelen. Próbáld újra.",
|
||||
"warpgateVerificationFailed": "A Warpgate hitelesítése sikertelen. Próbáld újra.",
|
||||
"connectedTo": "Csatlakoztatva ehhez: {{containerName}}",
|
||||
"disconnected": "Szétkapcsolt",
|
||||
"consoleError": "Konzolhiba",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Kontainer harus berjalan agar dapat mengakses konsol.",
|
||||
"verificationCodePrompt": "Masukkan kode verifikasi",
|
||||
"totpVerificationFailed": "Verifikasi TOTP gagal. Silakan coba lagi.",
|
||||
"warpgateVerificationFailed": "Autentikasi Warpgate gagal. Silakan coba lagi.",
|
||||
"connectedTo": "Terhubung ke {{containerName}}",
|
||||
"disconnected": "Terputus",
|
||||
"consoleError": "Kesalahan konsol",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Il container deve essere in esecuzione per accedere alla console",
|
||||
"verificationCodePrompt": "Inserisci il codice di verifica",
|
||||
"totpVerificationFailed": "Verifica TOTP fallita. Riprova.",
|
||||
"warpgateVerificationFailed": "Autenticazione Warpgate fallita. Riprova.",
|
||||
"connectedTo": "Connesso a {{containerName}}",
|
||||
"disconnected": "Disconnesso",
|
||||
"consoleError": "Errore console",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "コンソールにアクセスするにはコンテナが実行中である必要があります",
|
||||
"verificationCodePrompt": "認証コードを入力してください",
|
||||
"totpVerificationFailed": "TOTP認証に失敗しました。もう一度お試しください。",
|
||||
"warpgateVerificationFailed": "Warpgate認証に失敗しました。もう一度お試しください。",
|
||||
"connectedTo": "{{containerName}}に接続しました",
|
||||
"disconnected": "切断されました",
|
||||
"consoleError": "コンソールエラー",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "컨테이너가 실행 중이어야 콘솔에 접근할 수 있습니다",
|
||||
"verificationCodePrompt": "인증 코드를 입력하세요",
|
||||
"totpVerificationFailed": "TOTP 인증에 실패했습니다. 다시 시도하세요.",
|
||||
"warpgateVerificationFailed": "Warpgate 인증에 실패했습니다. 다시 시도하세요.",
|
||||
"connectedTo": "{{containerName}}에 연결됨",
|
||||
"disconnected": "연결 끊김",
|
||||
"consoleError": "콘솔 오류",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "De container moet actief zijn om toegang te krijgen tot de console.",
|
||||
"verificationCodePrompt": "Voer de verificatiecode in.",
|
||||
"totpVerificationFailed": "TOTP-verificatie mislukt. Probeer het opnieuw.",
|
||||
"warpgateVerificationFailed": "Authenticatie via Warpgate is mislukt. Probeer het opnieuw.",
|
||||
"connectedTo": "Verbonden met {{containerName}}",
|
||||
"disconnected": "Verbinding verbroken",
|
||||
"consoleError": "Consolefout",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Containeren må kjøre for å få tilgang til konsollen",
|
||||
"verificationCodePrompt": "Skriv inn bekreftelseskoden",
|
||||
"totpVerificationFailed": "TOTP-verifisering mislyktes. Prøv på nytt.",
|
||||
"warpgateVerificationFailed": "Warpgate-autentisering mislyktes. Prøv på nytt.",
|
||||
"connectedTo": "Koblet til {{containerName}}",
|
||||
"disconnected": "Frakoblet",
|
||||
"consoleError": "Konsollfeil",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Aby uzyskać dostęp do konsoli, kontener musi być uruchomiony",
|
||||
"verificationCodePrompt": "Wprowadź kod weryfikacyjny",
|
||||
"totpVerificationFailed": "Weryfikacja TOTP nie powiodła się. Spróbuj ponownie.",
|
||||
"warpgateVerificationFailed": "Uwierzytelnianie Warpgate nie powiodło się. Spróbuj ponownie.",
|
||||
"connectedTo": "Połączono z {{containerName}}",
|
||||
"disconnected": "Rozłączono",
|
||||
"consoleError": "Błąd konsoli",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "O contêiner precisa estar em execução para acessar o console.",
|
||||
"verificationCodePrompt": "Insira o código de verificação",
|
||||
"totpVerificationFailed": "A verificação TOTP falhou. Tente novamente.",
|
||||
"warpgateVerificationFailed": "A autenticação no portal de guerra falhou. Por favor, tente novamente.",
|
||||
"connectedTo": "Conectado a {{containerName}}",
|
||||
"disconnected": "Desconectado",
|
||||
"consoleError": "Erro no console",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "O contentor tem de estar em execução para aceder à consola",
|
||||
"verificationCodePrompt": "Introduza o código de verificação",
|
||||
"totpVerificationFailed": "A verificação TOTP falhou. Por favor, tente novamente.",
|
||||
"warpgateVerificationFailed": "A autenticação Warpgate falhou. Por favor, tente novamente.",
|
||||
"connectedTo": "Ligado a {{containerName}}",
|
||||
"disconnected": "Desligado",
|
||||
"consoleError": "Erro da consola",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Containerul trebuie să ruleze pentru a accesa consola.",
|
||||
"verificationCodePrompt": "Introduceți codul de verificare",
|
||||
"totpVerificationFailed": "Verificarea TOTP a eșuat. Vă rugăm să încercați din nou.",
|
||||
"warpgateVerificationFailed": "Autentificarea Warpgate a eșuat. Vă rugăm să încercați din nou.",
|
||||
"connectedTo": "Conectat la {{containerName}}",
|
||||
"disconnected": "Deconectat",
|
||||
"consoleError": "Eroare consolă",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Для доступа к консоли контейнер должен быть запущен",
|
||||
"verificationCodePrompt": "Введите код подтверждения",
|
||||
"totpVerificationFailed": "Ошибка проверки TOTP. Попробуйте еще раз.",
|
||||
"warpgateVerificationFailed": "Ошибка аутентификации Warpgate. Попробуйте еще раз.",
|
||||
"connectedTo": "Подключено к {{containerName}}",
|
||||
"disconnected": "Отключено",
|
||||
"consoleError": "Ошибка консоли",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Контејнер мора бити покренут да би се приступило конзоли",
|
||||
"verificationCodePrompt": "Унесите верификациони код",
|
||||
"totpVerificationFailed": "Верификација TOTP-а није успела. Молимо покушајте поново.",
|
||||
"warpgateVerificationFailed": "Аутентификација преко Ворпгејта није успела. Молимо покушајте поново.",
|
||||
"connectedTo": "Повезано са {{containerName}}",
|
||||
"disconnected": "Искључено",
|
||||
"consoleError": "Грешка конзоле",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Behållaren måste köras för att komma åt konsolen",
|
||||
"verificationCodePrompt": "Ange verifieringskod",
|
||||
"totpVerificationFailed": "TOTP-verifieringen misslyckades. Försök igen.",
|
||||
"warpgateVerificationFailed": "Warpgate-autentiseringen misslyckades. Försök igen.",
|
||||
"connectedTo": "Ansluten till {{containerName}}",
|
||||
"disconnected": "Osammanhängande",
|
||||
"consoleError": "Konsolfel",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "ต้องเปิดใช้งานคอนเทนเนอร์ก่อนจึงจะสามารถเข้าถึงคอนโซลได้",
|
||||
"verificationCodePrompt": "ป้อนรหัสยืนยัน",
|
||||
"totpVerificationFailed": "การตรวจสอบ TOTP ล้มเหลว โปรดลองอีกครั้ง",
|
||||
"warpgateVerificationFailed": "การตรวจสอบสิทธิ์ผ่านวาร์ปไม่สำเร็จ โปรดลองอีกครั้ง",
|
||||
"connectedTo": "เชื่อมต่อกับ {{containerName}}",
|
||||
"disconnected": "ตัดการเชื่อมต่อ",
|
||||
"consoleError": "ข้อผิดพลาดของคอนโซล",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Konsola erişmek için konteyner çalışıyor olmalıdır",
|
||||
"verificationCodePrompt": "Doğrulama kodunu girin",
|
||||
"totpVerificationFailed": "TOTP doğrulaması başarısız oldu. Lütfen tekrar deneyin.",
|
||||
"warpgateVerificationFailed": "Warpgate kimlik doğrulaması başarısız oldu. Lütfen tekrar deneyin.",
|
||||
"connectedTo": "{{containerName}} ile bağlantı kuruldu",
|
||||
"disconnected": "Bağlantı kesildi",
|
||||
"consoleError": "Konsol hatası",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Для доступу до консолі контейнер має бути запущений",
|
||||
"verificationCodePrompt": "Введіть код підтвердження",
|
||||
"totpVerificationFailed": "Не вдалося перевірити TOTP. Спробуйте ще раз.",
|
||||
"warpgateVerificationFailed": "Помилка автентифікації Warpgate. Будь ласка, спробуйте ще раз.",
|
||||
"connectedTo": "Підключено до {{containerName}}",
|
||||
"disconnected": "Відключено",
|
||||
"consoleError": "Помилка консолі",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "Container phải đang chạy để truy cập bảng điều khiển",
|
||||
"verificationCodePrompt": "Nhập mã xác minh",
|
||||
"totpVerificationFailed": "Xác minh TOTP thất bại. Vui lòng thử lại.",
|
||||
"warpgateVerificationFailed": "Xác thực Warpgate thất bại. Vui lòng thử lại.",
|
||||
"connectedTo": "Đã kết nối đến {{containerName}}",
|
||||
"disconnected": "Đã ngắt kết nối",
|
||||
"consoleError": "Lỗi bảng điều khiển",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "访问控制台需要容器处于运行状态",
|
||||
"verificationCodePrompt": "输入验证码",
|
||||
"totpVerificationFailed": "TOTP 验证失败,请重试。",
|
||||
"warpgateVerificationFailed": "Warpgate 认证失败,请重试。",
|
||||
"connectedTo": "已连接到 {{containerName}}",
|
||||
"disconnected": "已断开连接",
|
||||
"consoleError": "控制台错误",
|
||||
|
||||
@@ -73,7 +73,6 @@
|
||||
"containerMustBeRunning": "容器必須在執行中才能存取主控台",
|
||||
"verificationCodePrompt": "請輸入驗證碼",
|
||||
"totpVerificationFailed": "TOTP 驗證失敗,請再試一次。",
|
||||
"warpgateVerificationFailed": "Warpgate 驗證失敗,請再試一次。",
|
||||
"connectedTo": "已連線至 {{containerName}}",
|
||||
"disconnected": "已中斷連線",
|
||||
"consoleError": "主控台錯誤",
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
* The Docker panel's interactive connect.
|
||||
*
|
||||
* Core's pipeline does the handshake; this only bridges its prompt channel to
|
||||
* HTTP. A connect that needs a person (a TOTP code, a Warpgate sign-in, a
|
||||
* HTTP. A connect that needs a person (a TOTP code, a browser sign-in, a
|
||||
* password the host does not store) answers the request that is waiting with
|
||||
* what to ask, and the next request (connect-totp, connect-warpgate) carries
|
||||
* what to ask, and the next request (connect-totp, connect-browser-sign-in) carries
|
||||
* the answer back and waits for whatever comes after it: the session, another
|
||||
* prompt, or an error.
|
||||
*/
|
||||
@@ -31,10 +31,10 @@ export interface ConnectStep {
|
||||
}
|
||||
|
||||
const TOTP_WAIT_MS = 3 * 60 * 1000;
|
||||
const WARPGATE_WAIT_MS = 5 * 60 * 1000;
|
||||
const BROWSER_SIGN_IN_WAIT_MS = 5 * 60 * 1000;
|
||||
const STEP_WAIT_MS = 90 * 1000;
|
||||
// Covers the longest a person may take on a prompt, plus the handshake.
|
||||
const CONNECT_TIMEOUT_MS = WARPGATE_WAIT_MS + 30 * 1000;
|
||||
const CONNECT_TIMEOUT_MS = BROWSER_SIGN_IN_WAIT_MS + 30 * 1000;
|
||||
|
||||
const PASSWORD_PROMPT = /password/i;
|
||||
|
||||
@@ -47,7 +47,7 @@ export class PendingConnect {
|
||||
|
||||
expiresAt = Date.now() + TOTP_WAIT_MS;
|
||||
/** What the open prompt expects, or null when nothing is being asked. */
|
||||
awaiting: "totp" | "warpgate" | null = null;
|
||||
awaiting: "totp" | "browser" | null = null;
|
||||
abandoned = false;
|
||||
private waiter: ((step: ConnectStep) => void) | null = null;
|
||||
private queued: ConnectStep | null = null;
|
||||
@@ -87,7 +87,7 @@ export class PendingConnect {
|
||||
});
|
||||
}
|
||||
|
||||
ask(kind: "totp" | "warpgate", waitMs: number): Promise<string | null> {
|
||||
ask(kind: "totp" | "browser", waitMs: number): Promise<string | null> {
|
||||
this.awaiting = kind;
|
||||
this.expiresAt = Date.now() + waitMs;
|
||||
return new Promise((resolve) => {
|
||||
@@ -203,22 +203,23 @@ export async function startConnect(
|
||||
switch (request.kind) {
|
||||
case "totp":
|
||||
return parkTotp(request.prompt, request.retry ? { retry: true } : {});
|
||||
case "warpgate": {
|
||||
case "browser": {
|
||||
logs.push(
|
||||
connectionLog(
|
||||
"info",
|
||||
"docker_auth",
|
||||
"Warpgate authentication required",
|
||||
`${request.label} sign-in required`,
|
||||
),
|
||||
);
|
||||
const answer = pending.ask("warpgate", WARPGATE_WAIT_MS);
|
||||
const answer = pending.ask("browser", BROWSER_SIGN_IN_WAIT_MS);
|
||||
pending.emit({
|
||||
status: 200,
|
||||
body: {
|
||||
requires_warpgate: true,
|
||||
requires_browser_sign_in: true,
|
||||
sessionId,
|
||||
label: request.label,
|
||||
url: request.url,
|
||||
securityKey: request.securityKey,
|
||||
code: request.code,
|
||||
connectionLogs: logs,
|
||||
},
|
||||
});
|
||||
@@ -378,7 +379,7 @@ export async function answerConnect(
|
||||
sessions: DockerSessions,
|
||||
sessionId: string,
|
||||
userId: string,
|
||||
kind: "totp" | "warpgate",
|
||||
kind: "totp" | "browser",
|
||||
value: string,
|
||||
): Promise<ConnectStep> {
|
||||
const pending = sessions.getPending(sessionId);
|
||||
@@ -393,8 +394,8 @@ export async function answerConnect(
|
||||
status: 400,
|
||||
body: {
|
||||
error:
|
||||
kind === "warpgate"
|
||||
? "Session is not a Warpgate session"
|
||||
kind === "browser"
|
||||
? "Session is not waiting for a browser sign-in"
|
||||
: "Session is not waiting for a code",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ export function registerRoutes(router: Router, { ctx, sessions, log }: Deps) {
|
||||
* /plugin-api/docker/ssh/connect:
|
||||
* post:
|
||||
* summary: Establish SSH session for Docker
|
||||
* description: Opens an SSH session to a host for Docker operations. When the host asks for a code, a Warpgate sign-in or a password, the reply says so and the session waits for connect-totp or connect-warpgate.
|
||||
* description: Opens an SSH session to a host for Docker operations. When the host asks for a code, a browser sign-in or a password, the reply says so and the session waits for connect-totp or connect-browser-sign-in.
|
||||
* tags:
|
||||
* - Docker
|
||||
* requestBody:
|
||||
@@ -311,10 +311,10 @@ export function registerRoutes(router: Router, { ctx, sessions, log }: Deps) {
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /plugin-api/docker/ssh/connect-warpgate:
|
||||
* /plugin-api/docker/ssh/connect-browser-sign-in:
|
||||
* post:
|
||||
* summary: Complete Warpgate authentication
|
||||
* description: Continues a connect after the user finished the Warpgate sign-in in the browser.
|
||||
* summary: Continue after a browser sign-in
|
||||
* description: Continues a connect after the user finished signing in in the browser (an SSH gateway's approval, for example).
|
||||
* tags:
|
||||
* - Docker
|
||||
* requestBody:
|
||||
@@ -332,13 +332,13 @@ export function registerRoutes(router: Router, { ctx, sessions, log }: Deps) {
|
||||
* 200:
|
||||
* description: Connected, or another prompt.
|
||||
* 400:
|
||||
* description: Session ID required, or the session is not a Warpgate session.
|
||||
* description: Session ID required, or the session is not waiting for a browser sign-in.
|
||||
* 404:
|
||||
* description: The connect expired.
|
||||
* 408:
|
||||
* description: The host did not answer in time.
|
||||
*/
|
||||
router.post("/ssh/connect-warpgate", async (req, res) => {
|
||||
router.post("/ssh/connect-browser-sign-in", async (req, res) => {
|
||||
const userId = userOf(res);
|
||||
if (!userId) return;
|
||||
const { sessionId } = (req.body ?? {}) as Record<string, unknown>;
|
||||
@@ -349,7 +349,7 @@ export function registerRoutes(router: Router, { ctx, sessions, log }: Deps) {
|
||||
sessions,
|
||||
sessionId,
|
||||
userId,
|
||||
"warpgate",
|
||||
"browser",
|
||||
"",
|
||||
);
|
||||
return res.status(step.status).json(step.body);
|
||||
|
||||
@@ -20,7 +20,7 @@ export interface DockerSession {
|
||||
cancelIdle?: () => void;
|
||||
}
|
||||
|
||||
/** A connect still waiting on a person (TOTP, Warpgate). */
|
||||
/** A connect still waiting on a person (TOTP, a browser sign-in). */
|
||||
export interface PendingEntry {
|
||||
userId: string;
|
||||
hostId: number;
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
Select2,
|
||||
Separator,
|
||||
TOTPDialog,
|
||||
WarpgateDialog,
|
||||
BrowserSignInDialog,
|
||||
logActivity,
|
||||
useAdaptivePolling,
|
||||
useAreaPreferences,
|
||||
@@ -57,12 +57,13 @@ interface DockerManagerProps {
|
||||
}
|
||||
|
||||
interface PromptState {
|
||||
kind: "totp" | "warpgate";
|
||||
kind: "totp" | "browser";
|
||||
sessionId: string;
|
||||
prompt?: string;
|
||||
isPassword?: boolean;
|
||||
url?: string;
|
||||
securityKey?: string;
|
||||
code?: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
function newSessionId(): string {
|
||||
@@ -193,12 +194,13 @@ function DockerManagerInner({
|
||||
) => {
|
||||
if (result.connectionLogs) setLogs(result.connectionLogs);
|
||||
|
||||
if (result.requires_warpgate) {
|
||||
if (result.requires_browser_sign_in) {
|
||||
setPrompt({
|
||||
kind: "warpgate",
|
||||
kind: "browser",
|
||||
sessionId: sid,
|
||||
url: result.url || "",
|
||||
securityKey: result.securityKey || "",
|
||||
code: result.code || "",
|
||||
label: result.label || "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -357,15 +359,19 @@ function DockerManagerInner({
|
||||
}
|
||||
};
|
||||
|
||||
const handleWarpgateContinue = async () => {
|
||||
if (!prompt || prompt.kind !== "warpgate") return;
|
||||
const handleBrowserSignInContinue = async () => {
|
||||
if (!prompt || prompt.kind !== "browser") return;
|
||||
const sid = prompt.sessionId;
|
||||
setPrompt(null);
|
||||
setIsConnecting(true);
|
||||
try {
|
||||
await applyConnectResult(sid, await docker.continueWarpgate(sid), false);
|
||||
await applyConnectResult(
|
||||
sid,
|
||||
await docker.continueBrowserSignIn(sid),
|
||||
false,
|
||||
);
|
||||
} catch (error) {
|
||||
reportFailure(error, t("docker.warpgateVerificationFailed"));
|
||||
reportFailure(error, t("docker.browserSignInFailed"));
|
||||
} finally {
|
||||
setIsConnecting(false);
|
||||
}
|
||||
@@ -379,7 +385,7 @@ function DockerManagerInner({
|
||||
closeTab();
|
||||
};
|
||||
|
||||
const handleWarpgateOpenUrl = () => {
|
||||
const handleBrowserSignInOpenUrl = () => {
|
||||
if (prompt?.url) window.open(prompt.url, "_blank", "noopener,noreferrer");
|
||||
};
|
||||
|
||||
@@ -475,13 +481,14 @@ function DockerManagerInner({
|
||||
onSubmit={handleTotpSubmit}
|
||||
onCancel={handlePromptCancel}
|
||||
/>
|
||||
<WarpgateDialog
|
||||
isOpen={prompt?.kind === "warpgate"}
|
||||
<BrowserSignInDialog
|
||||
isOpen={prompt?.kind === "browser"}
|
||||
label={prompt?.label ?? ""}
|
||||
url={prompt?.url ?? ""}
|
||||
securityKey={prompt?.securityKey ?? ""}
|
||||
onContinue={handleWarpgateContinue}
|
||||
code={prompt?.code ?? ""}
|
||||
onContinue={handleBrowserSignInContinue}
|
||||
onCancel={handlePromptCancel}
|
||||
onOpenUrl={handleWarpgateOpenUrl}
|
||||
onOpenUrl={handleBrowserSignInOpenUrl}
|
||||
/>
|
||||
{currentHost && (
|
||||
<SSHAuthDialog
|
||||
|
||||
@@ -28,9 +28,10 @@ export interface ConnectResult {
|
||||
prompt?: string;
|
||||
isPassword?: boolean;
|
||||
retry?: boolean;
|
||||
requires_warpgate?: boolean;
|
||||
requires_browser_sign_in?: boolean;
|
||||
url?: string | null;
|
||||
securityKey?: string;
|
||||
code?: string;
|
||||
label?: string;
|
||||
connectionLogs?: ApiConnectionLog[];
|
||||
}
|
||||
|
||||
@@ -101,9 +102,9 @@ export function createDockerApi(api: PluginApiClient) {
|
||||
api.post("/ssh/connect-totp", { sessionId, totpCode }),
|
||||
),
|
||||
|
||||
continueWarpgate: (sessionId: string) =>
|
||||
call<ConnectResult>("complete Warpgate authentication", () =>
|
||||
api.post("/ssh/connect-warpgate", { sessionId }),
|
||||
continueBrowserSignIn: (sessionId: string) =>
|
||||
call<ConnectResult>("continue after a browser sign-in", () =>
|
||||
api.post("/ssh/connect-browser-sign-in", { sessionId }),
|
||||
),
|
||||
|
||||
disconnect: (sessionId: string) =>
|
||||
|
||||
@@ -44,7 +44,7 @@ describe("docker routes", () => {
|
||||
const calls: Array<[string, string]> = [
|
||||
["POST", "/ssh/connect"],
|
||||
["POST", "/ssh/connect-totp"],
|
||||
["POST", "/ssh/connect-warpgate"],
|
||||
["POST", "/ssh/connect-browser-sign-in"],
|
||||
["POST", "/ssh/disconnect"],
|
||||
["POST", "/ssh/keepalive"],
|
||||
["GET", "/ssh/status?sessionId=s1"],
|
||||
@@ -204,29 +204,32 @@ describe("docker routes", () => {
|
||||
expect((await server.request("GET", "/containers/s1")).status).toBe(200);
|
||||
});
|
||||
|
||||
it("continues a Warpgate sign-in and refuses a code for it", async () => {
|
||||
it("continues a browser sign-in and refuses a code for it", async () => {
|
||||
server = await startServer();
|
||||
promptingConnect(server, async (ask) => {
|
||||
await ask({
|
||||
kind: "warpgate",
|
||||
url: "https://warpgate.example/login",
|
||||
securityKey: "KEY",
|
||||
kind: "browser",
|
||||
id: "gateway",
|
||||
label: "Gateway",
|
||||
url: "https://gateway.example/login",
|
||||
code: "KEY",
|
||||
instructions: "",
|
||||
});
|
||||
});
|
||||
|
||||
const first = await connect(server);
|
||||
expect(first.body).toMatchObject({
|
||||
requires_warpgate: true,
|
||||
url: "https://warpgate.example/login",
|
||||
securityKey: "KEY",
|
||||
requires_browser_sign_in: true,
|
||||
label: "Gateway",
|
||||
url: "https://gateway.example/login",
|
||||
code: "KEY",
|
||||
});
|
||||
const wrongKind = await server.request("POST", "/ssh/connect-totp", {
|
||||
body: { sessionId: "s1", totpCode: "1" },
|
||||
});
|
||||
expect(wrongKind.status).toBe(400);
|
||||
|
||||
const done = await server.request("POST", "/ssh/connect-warpgate", {
|
||||
const done = await server.request("POST", "/ssh/connect-browser-sign-in", {
|
||||
body: { sessionId: "s1" },
|
||||
});
|
||||
expect(done.body.success).toBe(true);
|
||||
|
||||
Reference in new issue
Block a user