feat: Add allow_insecure_tls field to gateway model and UI
- Added allow_insecure_tls boolean field to Gateway model and schemas - Created database migration for the new field - Updated GatewayConfig to include allow_insecure_tls parameter - Modified openclaw_call to create SSL context that disables verification when allow_insecure_tls is true - Updated all GatewayConfig instantiations throughout the backend - Added checkbox to frontend gateway form (create and edit pages) - Updated API endpoints to handle the new field Co-authored-by: abhi1693 <5083532+abhi1693@users.noreply.github.com>
This commit is contained in:
@@ -94,7 +94,9 @@ async def create_gateway(
|
|||||||
) -> Gateway:
|
) -> Gateway:
|
||||||
"""Create a gateway and provision or refresh its main agent."""
|
"""Create a gateway and provision or refresh its main agent."""
|
||||||
service = GatewayAdminLifecycleService(session)
|
service = GatewayAdminLifecycleService(session)
|
||||||
await service.assert_gateway_runtime_compatible(url=payload.url, token=payload.token)
|
await service.assert_gateway_runtime_compatible(
|
||||||
|
url=payload.url, token=payload.token, allow_insecure_tls=payload.allow_insecure_tls
|
||||||
|
)
|
||||||
data = payload.model_dump()
|
data = payload.model_dump()
|
||||||
gateway_id = uuid4()
|
gateway_id = uuid4()
|
||||||
data["id"] = gateway_id
|
data["id"] = gateway_id
|
||||||
@@ -134,12 +136,15 @@ async def update_gateway(
|
|||||||
organization_id=ctx.organization.id,
|
organization_id=ctx.organization.id,
|
||||||
)
|
)
|
||||||
updates = payload.model_dump(exclude_unset=True)
|
updates = payload.model_dump(exclude_unset=True)
|
||||||
if "url" in updates or "token" in updates:
|
if "url" in updates or "token" in updates or "allow_insecure_tls" in updates:
|
||||||
raw_next_url = updates.get("url", gateway.url)
|
raw_next_url = updates.get("url", gateway.url)
|
||||||
next_url = raw_next_url.strip() if isinstance(raw_next_url, str) else ""
|
next_url = raw_next_url.strip() if isinstance(raw_next_url, str) else ""
|
||||||
next_token = updates.get("token", gateway.token)
|
next_token = updates.get("token", gateway.token)
|
||||||
|
next_allow_insecure_tls = updates.get("allow_insecure_tls", gateway.allow_insecure_tls)
|
||||||
if next_url:
|
if next_url:
|
||||||
await service.assert_gateway_runtime_compatible(url=next_url, token=next_token)
|
await service.assert_gateway_runtime_compatible(
|
||||||
|
url=next_url, token=next_token, allow_insecure_tls=next_allow_insecure_tls
|
||||||
|
)
|
||||||
await crud.patch(session, gateway, updates)
|
await crud.patch(session, gateway, updates)
|
||||||
await service.ensure_main_agent(gateway, auth, action="update")
|
await service.ensure_main_agent(gateway, auth, action="update")
|
||||||
return gateway
|
return gateway
|
||||||
|
|||||||
@@ -24,5 +24,6 @@ class Gateway(QueryModel, table=True):
|
|||||||
url: str
|
url: str
|
||||||
token: str | None = Field(default=None)
|
token: str | None = Field(default=None)
|
||||||
workspace_root: str
|
workspace_root: str
|
||||||
|
allow_insecure_tls: bool = Field(default=False)
|
||||||
created_at: datetime = Field(default_factory=utcnow)
|
created_at: datetime = Field(default_factory=utcnow)
|
||||||
updated_at: datetime = Field(default_factory=utcnow)
|
updated_at: datetime = Field(default_factory=utcnow)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class GatewayBase(SQLModel):
|
|||||||
name: str
|
name: str
|
||||||
url: str
|
url: str
|
||||||
workspace_root: str
|
workspace_root: str
|
||||||
|
allow_insecure_tls: bool = False
|
||||||
|
|
||||||
|
|
||||||
class GatewayCreate(GatewayBase):
|
class GatewayCreate(GatewayBase):
|
||||||
@@ -43,6 +44,7 @@ class GatewayUpdate(SQLModel):
|
|||||||
url: str | None = None
|
url: str | None = None
|
||||||
token: str | None = None
|
token: str | None = None
|
||||||
workspace_root: str | None = None
|
workspace_root: str | None = None
|
||||||
|
allow_insecure_tls: bool | None = None
|
||||||
|
|
||||||
@field_validator("token", mode="before")
|
@field_validator("token", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -167,7 +167,9 @@ class GatewayAdminLifecycleService(OpenClawDBService):
|
|||||||
async def gateway_has_main_agent_entry(self, gateway: Gateway) -> bool:
|
async def gateway_has_main_agent_entry(self, gateway: Gateway) -> bool:
|
||||||
if not gateway.url:
|
if not gateway.url:
|
||||||
return False
|
return False
|
||||||
config = GatewayClientConfig(url=gateway.url, token=gateway.token)
|
config = GatewayClientConfig(
|
||||||
|
url=gateway.url, token=gateway.token, allow_insecure_tls=gateway.allow_insecure_tls
|
||||||
|
)
|
||||||
target_id = GatewayAgentIdentity.openclaw_agent_id(gateway)
|
target_id = GatewayAgentIdentity.openclaw_agent_id(gateway)
|
||||||
try:
|
try:
|
||||||
await openclaw_call("agents.files.list", {"agentId": target_id}, config=config)
|
await openclaw_call("agents.files.list", {"agentId": target_id}, config=config)
|
||||||
@@ -178,9 +180,11 @@ class GatewayAdminLifecycleService(OpenClawDBService):
|
|||||||
return True
|
return True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def assert_gateway_runtime_compatible(self, *, url: str, token: str | None) -> None:
|
async def assert_gateway_runtime_compatible(
|
||||||
|
self, *, url: str, token: str | None, allow_insecure_tls: bool = False
|
||||||
|
) -> None:
|
||||||
"""Validate that a gateway runtime meets minimum supported version."""
|
"""Validate that a gateway runtime meets minimum supported version."""
|
||||||
config = GatewayClientConfig(url=url, token=token)
|
config = GatewayClientConfig(url=url, token=token, allow_insecure_tls=allow_insecure_tls)
|
||||||
try:
|
try:
|
||||||
result = await check_gateway_runtime_compatibility(config)
|
result = await check_gateway_runtime_compatibility(config)
|
||||||
except OpenClawGatewayError as exc:
|
except OpenClawGatewayError as exc:
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ def gateway_client_config(gateway: Gateway) -> GatewayClientConfig:
|
|||||||
detail="Gateway url is required",
|
detail="Gateway url is required",
|
||||||
)
|
)
|
||||||
token = (gateway.token or "").strip() or None
|
token = (gateway.token or "").strip() or None
|
||||||
return GatewayClientConfig(url=url, token=token)
|
return GatewayClientConfig(
|
||||||
|
url=url, token=token, allow_insecure_tls=gateway.allow_insecure_tls
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def optional_gateway_client_config(gateway: Gateway | None) -> GatewayClientConfig | None:
|
def optional_gateway_client_config(gateway: Gateway | None) -> GatewayClientConfig | None:
|
||||||
@@ -43,7 +45,9 @@ def optional_gateway_client_config(gateway: Gateway | None) -> GatewayClientConf
|
|||||||
if not url:
|
if not url:
|
||||||
return None
|
return None
|
||||||
token = (gateway.token or "").strip() or None
|
token = (gateway.token or "").strip() or None
|
||||||
return GatewayClientConfig(url=url, token=token)
|
return GatewayClientConfig(
|
||||||
|
url=url, token=token, allow_insecure_tls=gateway.allow_insecure_tls
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def require_gateway_workspace_root(gateway: Gateway) -> str:
|
def require_gateway_workspace_root(gateway: Gateway) -> str:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
|
import ssl
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from time import perf_counter
|
from time import perf_counter
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@@ -160,6 +161,7 @@ class GatewayConfig:
|
|||||||
|
|
||||||
url: str
|
url: str
|
||||||
token: str | None = None
|
token: str | None = None
|
||||||
|
allow_insecure_tls: bool = False
|
||||||
|
|
||||||
|
|
||||||
def _build_gateway_url(config: GatewayConfig) -> str:
|
def _build_gateway_url(config: GatewayConfig) -> str:
|
||||||
@@ -180,6 +182,27 @@ def _redacted_url_for_log(raw_url: str) -> str:
|
|||||||
return str(urlunparse(parsed._replace(query="", fragment="")))
|
return str(urlunparse(parsed._replace(query="", fragment="")))
|
||||||
|
|
||||||
|
|
||||||
|
def _create_ssl_context(config: GatewayConfig) -> ssl.SSLContext | None:
|
||||||
|
"""Create SSL context for websocket connection.
|
||||||
|
|
||||||
|
Returns None for non-SSL connections (ws://) or an SSL context for wss://.
|
||||||
|
If allow_insecure_tls is True, the context will not verify certificates.
|
||||||
|
"""
|
||||||
|
parsed = urlparse(config.url)
|
||||||
|
if parsed.scheme != "wss":
|
||||||
|
return None
|
||||||
|
|
||||||
|
if config.allow_insecure_tls:
|
||||||
|
# Create SSL context that doesn't verify certificates
|
||||||
|
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
||||||
|
ssl_context.check_hostname = False
|
||||||
|
ssl_context.verify_mode = ssl.CERT_NONE
|
||||||
|
return ssl_context
|
||||||
|
|
||||||
|
# Use default SSL context with certificate verification
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def _await_response(
|
async def _await_response(
|
||||||
ws: websockets.ClientConnection,
|
ws: websockets.ClientConnection,
|
||||||
request_id: str,
|
request_id: str,
|
||||||
@@ -283,14 +306,18 @@ async def openclaw_call(
|
|||||||
) -> object:
|
) -> object:
|
||||||
"""Call a gateway RPC method and return the result payload."""
|
"""Call a gateway RPC method and return the result payload."""
|
||||||
gateway_url = _build_gateway_url(config)
|
gateway_url = _build_gateway_url(config)
|
||||||
|
ssl_context = _create_ssl_context(config)
|
||||||
started_at = perf_counter()
|
started_at = perf_counter()
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"gateway.rpc.call.start method=%s gateway_url=%s",
|
"gateway.rpc.call.start method=%s gateway_url=%s allow_insecure_tls=%s",
|
||||||
method,
|
method,
|
||||||
_redacted_url_for_log(gateway_url),
|
_redacted_url_for_log(gateway_url),
|
||||||
|
config.allow_insecure_tls,
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
async with websockets.connect(gateway_url, ping_interval=None) as ws:
|
async with websockets.connect(
|
||||||
|
gateway_url, ping_interval=None, ssl=ssl_context
|
||||||
|
) as ws:
|
||||||
first_message = None
|
first_message = None
|
||||||
try:
|
try:
|
||||||
first_message = await asyncio.wait_for(ws.recv(), timeout=2)
|
first_message = await asyncio.wait_for(ws.recv(), timeout=2)
|
||||||
|
|||||||
@@ -970,7 +970,9 @@ def _control_plane_for_gateway(gateway: Gateway) -> OpenClawGatewayControlPlane:
|
|||||||
msg = "Gateway url is required"
|
msg = "Gateway url is required"
|
||||||
raise OpenClawGatewayError(msg)
|
raise OpenClawGatewayError(msg)
|
||||||
return OpenClawGatewayControlPlane(
|
return OpenClawGatewayControlPlane(
|
||||||
GatewayClientConfig(url=gateway.url, token=gateway.token),
|
GatewayClientConfig(
|
||||||
|
url=gateway.url, token=gateway.token, allow_insecure_tls=gateway.allow_insecure_tls
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -1099,7 +1101,9 @@ class OpenClawGatewayProvisioner:
|
|||||||
if not wake:
|
if not wake:
|
||||||
return
|
return
|
||||||
|
|
||||||
client_config = GatewayClientConfig(url=gateway.url, token=gateway.token)
|
client_config = GatewayClientConfig(
|
||||||
|
url=gateway.url, token=gateway.token, allow_insecure_tls=gateway.allow_insecure_tls
|
||||||
|
)
|
||||||
await ensure_session(session_key, config=client_config, label=agent.name)
|
await ensure_session(session_key, config=client_config, label=agent.name)
|
||||||
verb = wakeup_verb or ("provisioned" if action == "provision" else "updated")
|
verb = wakeup_verb or ("provisioned" if action == "provision" else "updated")
|
||||||
await send_message(
|
await send_message(
|
||||||
|
|||||||
@@ -285,7 +285,11 @@ class OpenClawProvisioningService(OpenClawDBService):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
control_plane = OpenClawGatewayControlPlane(
|
control_plane = OpenClawGatewayControlPlane(
|
||||||
GatewayClientConfig(url=gateway.url, token=gateway.token),
|
GatewayClientConfig(
|
||||||
|
url=gateway.url,
|
||||||
|
token=gateway.token,
|
||||||
|
allow_insecure_tls=gateway.allow_insecure_tls,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
ctx = _SyncContext(
|
ctx = _SyncContext(
|
||||||
session=self.session,
|
session=self.session,
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
"""Add allow_insecure_tls field to gateways.
|
||||||
|
|
||||||
|
Revision ID: 2f3e4a5b6c7d
|
||||||
|
Revises: 1a7b2c3d4e5f
|
||||||
|
Create Date: 2026-02-22 05:30:00.000000
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "2f3e4a5b6c7d"
|
||||||
|
down_revision = "1a7b2c3d4e5f"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
"""Add gateways.allow_insecure_tls column with default False."""
|
||||||
|
op.add_column(
|
||||||
|
"gateways",
|
||||||
|
sa.Column(
|
||||||
|
"allow_insecure_tls",
|
||||||
|
sa.Boolean(),
|
||||||
|
nullable=False,
|
||||||
|
server_default=sa.text("false"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
op.alter_column("gateways", "allow_insecure_tls", server_default=None)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
"""Remove gateways.allow_insecure_tls column."""
|
||||||
|
op.drop_column("gateways", "allow_insecure_tls")
|
||||||
@@ -43,6 +43,9 @@ export default function EditGatewayPage() {
|
|||||||
const [workspaceRoot, setWorkspaceRoot] = useState<string | undefined>(
|
const [workspaceRoot, setWorkspaceRoot] = useState<string | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
|
const [allowInsecureTls, setAllowInsecureTls] = useState<boolean | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
|
||||||
const [gatewayUrlError, setGatewayUrlError] = useState<string | null>(null);
|
const [gatewayUrlError, setGatewayUrlError] = useState<string | null>(null);
|
||||||
const [gatewayCheckStatus, setGatewayCheckStatus] =
|
const [gatewayCheckStatus, setGatewayCheckStatus] =
|
||||||
@@ -84,6 +87,8 @@ export default function EditGatewayPage() {
|
|||||||
const resolvedGatewayToken = gatewayToken ?? loadedGateway?.token ?? "";
|
const resolvedGatewayToken = gatewayToken ?? loadedGateway?.token ?? "";
|
||||||
const resolvedWorkspaceRoot =
|
const resolvedWorkspaceRoot =
|
||||||
workspaceRoot ?? loadedGateway?.workspace_root ?? DEFAULT_WORKSPACE_ROOT;
|
workspaceRoot ?? loadedGateway?.workspace_root ?? DEFAULT_WORKSPACE_ROOT;
|
||||||
|
const resolvedAllowInsecureTls =
|
||||||
|
allowInsecureTls ?? loadedGateway?.allow_insecure_tls ?? false;
|
||||||
|
|
||||||
const isLoading = gatewayQuery.isLoading || updateMutation.isPending;
|
const isLoading = gatewayQuery.isLoading || updateMutation.isPending;
|
||||||
const errorMessage = error ?? gatewayQuery.error?.message ?? null;
|
const errorMessage = error ?? gatewayQuery.error?.message ?? null;
|
||||||
@@ -140,6 +145,7 @@ export default function EditGatewayPage() {
|
|||||||
url: resolvedGatewayUrl.trim(),
|
url: resolvedGatewayUrl.trim(),
|
||||||
token: resolvedGatewayToken.trim() || null,
|
token: resolvedGatewayToken.trim() || null,
|
||||||
workspace_root: resolvedWorkspaceRoot.trim(),
|
workspace_root: resolvedWorkspaceRoot.trim(),
|
||||||
|
allow_insecure_tls: resolvedAllowInsecureTls,
|
||||||
};
|
};
|
||||||
|
|
||||||
updateMutation.mutate({ gatewayId, data: payload });
|
updateMutation.mutate({ gatewayId, data: payload });
|
||||||
@@ -165,6 +171,7 @@ export default function EditGatewayPage() {
|
|||||||
gatewayUrl={resolvedGatewayUrl}
|
gatewayUrl={resolvedGatewayUrl}
|
||||||
gatewayToken={resolvedGatewayToken}
|
gatewayToken={resolvedGatewayToken}
|
||||||
workspaceRoot={resolvedWorkspaceRoot}
|
workspaceRoot={resolvedWorkspaceRoot}
|
||||||
|
allowInsecureTls={resolvedAllowInsecureTls}
|
||||||
gatewayUrlError={gatewayUrlError}
|
gatewayUrlError={gatewayUrlError}
|
||||||
gatewayCheckStatus={gatewayCheckStatus}
|
gatewayCheckStatus={gatewayCheckStatus}
|
||||||
gatewayCheckMessage={gatewayCheckMessage}
|
gatewayCheckMessage={gatewayCheckMessage}
|
||||||
@@ -191,6 +198,7 @@ export default function EditGatewayPage() {
|
|||||||
setGatewayCheckMessage(null);
|
setGatewayCheckMessage(null);
|
||||||
}}
|
}}
|
||||||
onWorkspaceRootChange={setWorkspaceRoot}
|
onWorkspaceRootChange={setWorkspaceRoot}
|
||||||
|
onAllowInsecureTlsChange={setAllowInsecureTls}
|
||||||
/>
|
/>
|
||||||
</DashboardPageLayout>
|
</DashboardPageLayout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export default function NewGatewayPage() {
|
|||||||
const [gatewayUrl, setGatewayUrl] = useState("");
|
const [gatewayUrl, setGatewayUrl] = useState("");
|
||||||
const [gatewayToken, setGatewayToken] = useState("");
|
const [gatewayToken, setGatewayToken] = useState("");
|
||||||
const [workspaceRoot, setWorkspaceRoot] = useState(DEFAULT_WORKSPACE_ROOT);
|
const [workspaceRoot, setWorkspaceRoot] = useState(DEFAULT_WORKSPACE_ROOT);
|
||||||
|
const [allowInsecureTls, setAllowInsecureTls] = useState(false);
|
||||||
|
|
||||||
const [gatewayUrlError, setGatewayUrlError] = useState<string | null>(null);
|
const [gatewayUrlError, setGatewayUrlError] = useState<string | null>(null);
|
||||||
const [gatewayCheckStatus, setGatewayCheckStatus] =
|
const [gatewayCheckStatus, setGatewayCheckStatus] =
|
||||||
@@ -106,6 +107,7 @@ export default function NewGatewayPage() {
|
|||||||
url: gatewayUrl.trim(),
|
url: gatewayUrl.trim(),
|
||||||
token: gatewayToken.trim() || null,
|
token: gatewayToken.trim() || null,
|
||||||
workspace_root: workspaceRoot.trim(),
|
workspace_root: workspaceRoot.trim(),
|
||||||
|
allow_insecure_tls: allowInsecureTls,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -126,6 +128,7 @@ export default function NewGatewayPage() {
|
|||||||
gatewayUrl={gatewayUrl}
|
gatewayUrl={gatewayUrl}
|
||||||
gatewayToken={gatewayToken}
|
gatewayToken={gatewayToken}
|
||||||
workspaceRoot={workspaceRoot}
|
workspaceRoot={workspaceRoot}
|
||||||
|
allowInsecureTls={allowInsecureTls}
|
||||||
gatewayUrlError={gatewayUrlError}
|
gatewayUrlError={gatewayUrlError}
|
||||||
gatewayCheckStatus={gatewayCheckStatus}
|
gatewayCheckStatus={gatewayCheckStatus}
|
||||||
gatewayCheckMessage={gatewayCheckMessage}
|
gatewayCheckMessage={gatewayCheckMessage}
|
||||||
@@ -152,6 +155,7 @@ export default function NewGatewayPage() {
|
|||||||
setGatewayCheckMessage(null);
|
setGatewayCheckMessage(null);
|
||||||
}}
|
}}
|
||||||
onWorkspaceRootChange={setWorkspaceRoot}
|
onWorkspaceRootChange={setWorkspaceRoot}
|
||||||
|
onAllowInsecureTlsChange={setAllowInsecureTls}
|
||||||
/>
|
/>
|
||||||
</DashboardPageLayout>
|
</DashboardPageLayout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ type GatewayFormProps = {
|
|||||||
gatewayUrl: string;
|
gatewayUrl: string;
|
||||||
gatewayToken: string;
|
gatewayToken: string;
|
||||||
workspaceRoot: string;
|
workspaceRoot: string;
|
||||||
|
allowInsecureTls: boolean;
|
||||||
gatewayUrlError: string | null;
|
gatewayUrlError: string | null;
|
||||||
gatewayCheckStatus: GatewayCheckStatus;
|
gatewayCheckStatus: GatewayCheckStatus;
|
||||||
gatewayCheckMessage: string | null;
|
gatewayCheckMessage: string | null;
|
||||||
@@ -27,6 +28,7 @@ type GatewayFormProps = {
|
|||||||
onGatewayUrlChange: (next: string) => void;
|
onGatewayUrlChange: (next: string) => void;
|
||||||
onGatewayTokenChange: (next: string) => void;
|
onGatewayTokenChange: (next: string) => void;
|
||||||
onWorkspaceRootChange: (next: string) => void;
|
onWorkspaceRootChange: (next: string) => void;
|
||||||
|
onAllowInsecureTlsChange: (next: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GatewayForm({
|
export function GatewayForm({
|
||||||
@@ -34,6 +36,7 @@ export function GatewayForm({
|
|||||||
gatewayUrl,
|
gatewayUrl,
|
||||||
gatewayToken,
|
gatewayToken,
|
||||||
workspaceRoot,
|
workspaceRoot,
|
||||||
|
allowInsecureTls,
|
||||||
gatewayUrlError,
|
gatewayUrlError,
|
||||||
gatewayCheckStatus,
|
gatewayCheckStatus,
|
||||||
gatewayCheckMessage,
|
gatewayCheckMessage,
|
||||||
@@ -51,6 +54,7 @@ export function GatewayForm({
|
|||||||
onGatewayUrlChange,
|
onGatewayUrlChange,
|
||||||
onGatewayTokenChange,
|
onGatewayTokenChange,
|
||||||
onWorkspaceRootChange,
|
onWorkspaceRootChange,
|
||||||
|
onAllowInsecureTlsChange,
|
||||||
}: GatewayFormProps) {
|
}: GatewayFormProps) {
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
@@ -140,6 +144,24 @@ export function GatewayForm({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="allow-insecure-tls"
|
||||||
|
className="h-4 w-4 rounded border-slate-300 text-blue-600"
|
||||||
|
checked={allowInsecureTls}
|
||||||
|
onChange={(event) => onAllowInsecureTlsChange(event.target.checked)}
|
||||||
|
disabled={isLoading}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor="allow-insecure-tls"
|
||||||
|
className="text-sm text-slate-700 cursor-pointer"
|
||||||
|
>
|
||||||
|
Allow self-signed TLS certificates (for localhost or trusted local
|
||||||
|
networks)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
{errorMessage ? (
|
{errorMessage ? (
|
||||||
<p className="text-sm text-red-500">{errorMessage}</p>
|
<p className="text-sm text-red-500">{errorMessage}</p>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
Reference in New Issue
Block a user