hyperbrane 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -11
- package/dist/agent/agentClient.d.ts +5 -0
- package/dist/agent/agentClient.js +4 -0
- package/dist/agent/agentService.d.ts +9 -30
- package/dist/agent/agentService.js +62 -293
- package/dist/agent/agentStorage.d.ts +1 -20
- package/dist/agent/agentStorage.js +0 -30
- package/dist/agent/api.d.ts +89 -133
- package/dist/agent/api.js +4 -4
- package/dist/agent/client.d.ts +3 -1
- package/dist/agent/client.js +2 -3
- package/dist/agent/control.d.ts +23 -0
- package/dist/agent/control.js +479 -0
- package/dist/agent/hostTranscript.d.ts +0 -6
- package/dist/agent/hostTranscript.js +3 -14
- package/dist/agent/session/backend.d.ts +17 -30
- package/dist/agent/session/claude/home.d.ts +0 -1
- package/dist/agent/session/claude/home.js +0 -1
- package/dist/agent/session/claude/provision.d.ts +10 -0
- package/dist/agent/session/claude/provision.js +17 -0
- package/dist/agent/session/claude/transcript.d.ts +2 -7
- package/dist/agent/session/claude/transcript.js +68 -14
- package/dist/agent/session/client.d.ts +1 -10
- package/dist/agent/session/client.js +0 -3
- package/dist/agent/session/codex/provision.d.ts +14 -0
- package/dist/agent/session/codex/provision.js +25 -0
- package/dist/agent/session/fileTranscript.d.ts +6 -49
- package/dist/agent/session/fileTranscript.js +26 -82
- package/dist/agent/session/install.d.ts +5 -0
- package/dist/agent/session/install.js +35 -0
- package/dist/agent/session/sessionStorage.d.ts +4 -35
- package/dist/agent/session/sessionStorage.js +10 -16
- package/dist/agent/session/sharedConnection.d.ts +0 -8
- package/dist/agent/session/sharedConnection.js +0 -7
- package/dist/agent/session/storedTranscripts.d.ts +1 -6
- package/dist/agent/session/storedTranscripts.js +0 -3
- package/dist/agent/session/worker/jsonRpc.d.ts +2 -13
- package/dist/agent/session/worker/jsonRpc.js +2 -11
- package/dist/agent/session/worker/protocol.d.ts +27 -18
- package/dist/agent/session/worker/protocol.js +32 -16
- package/dist/agent/session/worker/workerParams.d.ts +0 -5
- package/dist/agent/session/worker/workerParams.js +15 -14
- package/dist/agent/session/workerConnection.d.ts +2 -13
- package/dist/agent/session/workerConnection.js +7 -12
- package/dist/agent/session/workerGatewayConnection.d.ts +18 -0
- package/dist/agent/session/workerGatewayConnection.js +86 -0
- package/dist/agent/vendor-types/manifest.json +87 -0
- package/dist/agent/workerBundle.d.ts +4 -19
- package/dist/agent/workerBundle.generated.js +1 -1
- package/dist/agent/workerBundle.js +3 -30
- package/dist/agent/workerReplacement.d.ts +3 -0
- package/dist/agent/workerReplacement.js +49 -0
- package/dist/cli/agent.js +44 -16
- package/dist/cli/command.d.ts +10 -11
- package/dist/cli/command.js +0 -4
- package/dist/cli/dimension.js +6 -6
- package/dist/cli/gateway.js +3 -6
- package/dist/cli/main.js +14 -31
- package/dist/cli/streamPrinter.d.ts +2 -10
- package/dist/cli/streamPrinter.js +16 -46
- package/dist/cli/table.d.ts +0 -3
- package/dist/cli/table.js +0 -4
- package/dist/dimension/api.d.ts +39 -27
- package/dist/dimension/api.js +28 -47
- package/dist/dimension/client.d.ts +5 -0
- package/dist/dimension/client.js +4 -0
- package/dist/dimension/control.d.ts +21 -0
- package/dist/dimension/control.js +328 -0
- package/dist/dimension/image.d.ts +0 -5
- package/dist/dimension/image.js +0 -8
- package/dist/dimension/imageFiles.generated.js +1 -1
- package/dist/dimension/paths.d.ts +5 -4
- package/dist/dimension/paths.js +15 -6
- package/dist/dimension/service.d.ts +8 -21
- package/dist/dimension/service.js +60 -224
- package/dist/dimension/transport-worker.d.ts +1 -0
- package/dist/dimension/transport-worker.js +151 -0
- package/dist/dimension/transportBundle.d.ts +2 -0
- package/dist/dimension/transportBundle.generated.d.ts +1 -0
- package/dist/dimension/transportBundle.generated.js +2 -0
- package/dist/dimension/transportBundle.js +4 -0
- package/dist/dimension/transportClient.d.ts +10 -0
- package/dist/dimension/transportClient.js +115 -0
- package/dist/dimension/transportProtocol.d.ts +53 -0
- package/dist/dimension/transportProtocol.js +8 -0
- package/dist/index.d.ts +5 -8
- package/dist/index.js +5 -16
- package/dist/lib/control.d.ts +8 -0
- package/dist/lib/control.js +62 -0
- package/dist/lib/docker.d.ts +0 -22
- package/dist/lib/docker.js +0 -10
- package/dist/lib/image.d.ts +0 -3
- package/dist/lib/image.js +0 -2
- package/dist/lib/jsonDirectory.d.ts +0 -13
- package/dist/lib/jsonDirectory.js +10 -15
- package/dist/lib/scriptBundle.d.ts +6 -0
- package/dist/lib/scriptBundle.js +28 -0
- package/dist/lib/sh.d.ts +2 -0
- package/dist/lib/sh.js +8 -0
- package/dist/lib/sleep.d.ts +0 -1
- package/dist/lib/sleep.js +0 -1
- package/dist/lib/streamFetch.d.ts +15 -0
- package/dist/lib/streamFetch.js +150 -0
- package/dist/lib/tar.d.ts +0 -1
- package/dist/lib/tar.js +5 -11
- package/dist/portal-gateway/api.d.ts +13 -44
- package/dist/portal-gateway/api.js +1 -3
- package/dist/portal-gateway/control.d.ts +42 -0
- package/dist/portal-gateway/control.js +657 -0
- package/dist/portal-gateway/gatewayClient.d.ts +5 -0
- package/dist/portal-gateway/gatewayClient.js +4 -0
- package/dist/portal-gateway/gatewayService.d.ts +8 -35
- package/dist/portal-gateway/gatewayService.js +79 -253
- package/dist/portal-gateway/image.d.ts +1 -2
- package/dist/portal-gateway/image.js +1 -3
- package/dist/portal-gateway/imageFiles.generated.js +3 -3
- package/dist/portal-gateway/portalClient.d.ts +5 -0
- package/dist/portal-gateway/portalClient.js +4 -0
- package/dist/portal-gateway/portalService.d.ts +5 -47
- package/dist/portal-gateway/portalService.js +19 -317
- package/dist/portal-gateway/transport-worker.d.ts +1 -0
- package/dist/portal-gateway/transport-worker.js +205 -0
- package/dist/portal-gateway/transportBundle.d.ts +2 -0
- package/dist/portal-gateway/transportBundle.generated.d.ts +1 -0
- package/dist/portal-gateway/transportBundle.generated.js +2 -0
- package/dist/portal-gateway/transportBundle.js +4 -0
- package/dist/portal-gateway/upstream.d.ts +12 -82
- package/dist/portal-gateway/upstream.js +0 -1
- package/dist/sandbox/api.d.ts +121 -178
- package/dist/sandbox/api.js +5 -7
- package/dist/sandbox/client.d.ts +2 -0
- package/dist/sandbox/client.js +4 -0
- package/dist/sandbox/data-endpoints/dataEndpoints.d.ts +13 -0
- package/dist/sandbox/data-endpoints/dataEndpoints.js +100 -0
- package/dist/sandbox/data-endpoints/firewalledPorts.d.ts +4 -0
- package/dist/sandbox/data-endpoints/firewalledPorts.js +28 -0
- package/dist/sandbox/lib/httpOverStream.d.ts +3 -0
- package/dist/sandbox/lib/httpOverStream.js +21 -0
- package/dist/sandbox/lib/remoteFileOperations.d.ts +10 -0
- package/dist/sandbox/lib/remoteFileOperations.js +70 -0
- package/dist/sandbox/lib/shellCommand.d.ts +3 -0
- package/dist/sandbox/lib/shellCommand.js +7 -0
- package/dist/sandbox/providers/boat/boatService.d.ts +2 -0
- package/dist/sandbox/providers/boat/boatService.js +321 -0
- package/dist/sandbox/providers/exedev/exeDevService.d.ts +2 -0
- package/dist/sandbox/providers/exedev/exeDevService.js +127 -0
- package/dist/sandbox/providers/exedev/exeDevToken.d.ts +1 -0
- package/dist/sandbox/providers/exedev/exeDevToken.js +54 -0
- package/dist/sandbox/providers/local/localService.d.ts +2 -0
- package/dist/sandbox/providers/local/localService.js +219 -0
- package/dist/sandbox/providers/ssh/sshService.d.ts +2 -0
- package/dist/sandbox/providers/ssh/sshService.js +82 -0
- package/dist/sandbox/providers/ssh/sshTransport.d.ts +12 -0
- package/dist/sandbox/providers/ssh/sshTransport.js +216 -0
- package/dist/sandbox/service.d.ts +2 -0
- package/dist/sandbox/service.js +18 -0
- package/dist/sandbox/storage/descriptors.d.ts +6 -0
- package/dist/sandbox/storage/descriptors.js +25 -0
- package/dist/sandbox/storage/sandboxStorage.d.ts +11 -0
- package/dist/sandbox/storage/sandboxStorage.js +42 -0
- package/dist/upstreams/anthropic.d.ts +0 -5
- package/dist/upstreams/anthropic.js +1 -8
- package/dist/upstreams/index.d.ts +2 -6
- package/dist/upstreams/index.js +0 -4
- package/dist/upstreams/openai.d.ts +0 -5
- package/dist/upstreams/openai.js +1 -13
- package/package.json +12 -4
- package/dist/agent/gatewaySignIns.d.ts +0 -5
- package/dist/agent/gatewaySignIns.js +0 -11
- package/dist/agent/session/codex/home.d.ts +0 -2
- package/dist/agent/session/codex/home.js +0 -4
- package/dist/agent/session/codex/messages.d.ts +0 -30
- package/dist/agent/session/codex/messages.js +0 -135
- package/dist/agent/session/codex/transcript.d.ts +0 -12
- package/dist/agent/session/codex/transcript.js +0 -22
- package/dist/agent/session/sdkMessages.d.ts +0 -15
- package/dist/agent/session/sdkMessages.js +0 -28
- package/dist/agent/session/workerSseConnection.d.ts +0 -15
- package/dist/agent/session/workerSseConnection.js +0 -26
- package/dist/agent/vendor-types/codex/app-server/AbsolutePathBuf.d.ts +0 -10
- package/dist/agent/vendor-types/codex/app-server/AbsolutePathBuf.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/FunctionCallOutputBody.d.ts +0 -2
- package/dist/agent/vendor-types/codex/app-server/FunctionCallOutputBody.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/FunctionCallOutputContentItem.d.ts +0 -22
- package/dist/agent/vendor-types/codex/app-server/FunctionCallOutputContentItem.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/ImageDetail.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/ImageDetail.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/ImageGenerationFailure.d.ts +0 -5
- package/dist/agent/vendor-types/codex/app-server/ImageGenerationFailure.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/ImageGenerationItem.d.ts +0 -11
- package/dist/agent/vendor-types/codex/app-server/ImageGenerationItem.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/LegacyAppPathString.d.ts +0 -23
- package/dist/agent/vendor-types/codex/app-server/LegacyAppPathString.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/MessagePhase.d.ts +0 -7
- package/dist/agent/vendor-types/codex/app-server/MessagePhase.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/ReasoningEffort.d.ts +0 -4
- package/dist/agent/vendor-types/codex/app-server/ReasoningEffort.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/SleepItem.d.ts +0 -7
- package/dist/agent/vendor-types/codex/app-server/SleepItem.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/WebSearchItem.d.ts +0 -14
- package/dist/agent/vendor-types/codex/app-server/WebSearchItem.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/serde_json/JsonValue.d.ts +0 -3
- package/dist/agent/vendor-types/codex/app-server/serde_json/JsonValue.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/AgentMessageDelivery.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/AgentMessageDelivery.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/AsyncUserInputQuestion.d.ts +0 -4
- package/dist/agent/vendor-types/codex/app-server/v2/AsyncUserInputQuestion.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/ByteRange.d.ts +0 -4
- package/dist/agent/vendor-types/codex/app-server/v2/ByteRange.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentState.d.ts +0 -5
- package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentState.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentStatus.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentStatus.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentTool.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentTool.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentToolCallStatus.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/CollabAgentToolCallStatus.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/CommandAction.d.ts +0 -19
- package/dist/agent/vendor-types/codex/app-server/v2/CommandAction.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/CommandExecutionSource.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/CommandExecutionSource.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/CommandExecutionStatus.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/CommandExecutionStatus.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/DynamicToolCallOutputContentItem.d.ts +0 -10
- package/dist/agent/vendor-types/codex/app-server/v2/DynamicToolCallOutputContentItem.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/DynamicToolCallStatus.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/DynamicToolCallStatus.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/FileUpdateChange.d.ts +0 -6
- package/dist/agent/vendor-types/codex/app-server/v2/FileUpdateChange.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/HookPromptFragment.d.ts +0 -4
- package/dist/agent/vendor-types/codex/app-server/v2/HookPromptFragment.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/McpAppDisplayMode.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/McpAppDisplayMode.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/McpAppUi.d.ts +0 -8
- package/dist/agent/vendor-types/codex/app-server/v2/McpAppUi.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallAppContext.d.ts +0 -7
- package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallAppContext.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallError.d.ts +0 -3
- package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallError.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallResult.d.ts +0 -6
- package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallResult.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallStatus.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/McpToolCallStatus.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/MemoryCitation.d.ts +0 -5
- package/dist/agent/vendor-types/codex/app-server/v2/MemoryCitation.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/MemoryCitationEntry.d.ts +0 -6
- package/dist/agent/vendor-types/codex/app-server/v2/MemoryCitationEntry.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/PatchApplyStatus.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/PatchApplyStatus.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/PatchChangeKind.d.ts +0 -8
- package/dist/agent/vendor-types/codex/app-server/v2/PatchChangeKind.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/SubAgentActivityKind.d.ts +0 -1
- package/dist/agent/vendor-types/codex/app-server/v2/SubAgentActivityKind.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/TextElement.d.ts +0 -11
- package/dist/agent/vendor-types/codex/app-server/v2/TextElement.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/ThreadItem.d.ts +0 -215
- package/dist/agent/vendor-types/codex/app-server/v2/ThreadItem.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/UserInput.d.ts +0 -35
- package/dist/agent/vendor-types/codex/app-server/v2/UserInput.js +0 -2
- package/dist/agent/vendor-types/codex/app-server/v2/WebSearchAction.d.ts +0 -14
- package/dist/agent/vendor-types/codex/app-server/v2/WebSearchAction.js +0 -2
- package/dist/cli/services.d.ts +0 -19
- package/dist/cli/services.js +0 -33
- package/dist/dimension/http.d.ts +0 -7
- package/dist/dimension/http.js +0 -77
- package/dist/dimension/storage.d.ts +0 -39
- package/dist/dimension/storage.js +0 -79
- package/dist/portal-gateway/fakes.d.ts +0 -3
- package/dist/portal-gateway/fakes.js +0 -11
- package/dist/portal-gateway/gatewayStorage.d.ts +0 -66
- package/dist/portal-gateway/gatewayStorage.js +0 -125
- package/dist/portal-gateway/portalStorage.d.ts +0 -34
- package/dist/portal-gateway/portalStorage.js +0 -44
- package/dist/sandbox/boatService.d.ts +0 -52
- package/dist/sandbox/boatService.js +0 -343
- package/dist/sandbox/containerService.d.ts +0 -15
- package/dist/sandbox/containerService.js +0 -184
- package/dist/sandbox/endpointProxy.d.ts +0 -90
- package/dist/sandbox/endpointProxy.js +0 -701
- package/dist/sandbox/exeDevAuth.d.ts +0 -16
- package/dist/sandbox/exeDevAuth.js +0 -49
- package/dist/sandbox/localService.d.ts +0 -19
- package/dist/sandbox/localService.js +0 -200
- package/dist/sandbox/sseConnection.d.ts +0 -41
- package/dist/sandbox/sseConnection.js +0 -166
- package/dist/sandbox/sshService.d.ts +0 -30
- package/dist/sandbox/sshService.js +0 -680
|
@@ -1,38 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import type { GatewayStorage } from "./gatewayStorage.ts";
|
|
6
|
-
import type { PortalStorage } from "./portalStorage.ts";
|
|
1
|
+
import type { Sandbox, SandboxDataEndpoint } from "../sandbox/api.ts";
|
|
2
|
+
import { type GatewayClient } from "./api.ts";
|
|
3
|
+
import { GATEWAY_STATE_PATH, gatewayCaCertificatePath, gatewayContainerName } from "./control.ts";
|
|
4
|
+
export { GATEWAY_STATE_PATH, gatewayCaCertificatePath, gatewayContainerName };
|
|
7
5
|
/** @sealed */
|
|
8
|
-
export interface GatewayService {
|
|
9
|
-
createGateway(gateway: Gateway): Promise<Gateway>;
|
|
10
|
-
destroyGateway(gatewayName: string): Promise<void>;
|
|
11
|
-
listGateways(): Promise<Gateway[]>;
|
|
12
|
-
restartGateway(gatewayName: string): Promise<void>;
|
|
13
|
-
listCredentials(gatewayName: string): Promise<GatewayCredential[]>;
|
|
14
|
-
deleteCredential(gatewayName: string, credentialName: string): Promise<void>;
|
|
15
|
-
registerUpstream(gatewayName: string, upstream: Upstream): Promise<Upstream>;
|
|
16
|
-
listUpstreams(gatewayName: string): Promise<Upstream[]>;
|
|
17
|
-
removeUpstream(gatewayName: string, upstreamName: string): Promise<void>;
|
|
18
|
-
setApiKey(gatewayName: string, upstreamName: string, keyName: string, key: string): Promise<{
|
|
19
|
-
fake: string;
|
|
20
|
-
}>;
|
|
21
|
-
deleteApiKey(gatewayName: string, upstreamName: string, keyName: string): Promise<void>;
|
|
22
|
-
createTrafficRule(gatewayName: string, rule: TrafficRule): Promise<TrafficRule>;
|
|
23
|
-
updateTrafficRule(gatewayName: string, rule: TrafficRule): Promise<TrafficRule>;
|
|
24
|
-
deleteTrafficRule(gatewayName: string, ruleName: string): Promise<void>;
|
|
25
|
-
listTrafficRules(gatewayName: string): Promise<TrafficRule[]>;
|
|
26
|
-
trafficRuleRespond(gatewayName: string, ruleName: string, action: "ALLOW" | "DENY"): Promise<void>;
|
|
6
|
+
export interface GatewayService extends GatewayClient {
|
|
27
7
|
}
|
|
28
|
-
/** Where the gateway's state directory is mounted in its container. */
|
|
29
|
-
export declare const GATEWAY_STATE_PATH = "/state";
|
|
30
|
-
export declare function gatewayContainerName(gatewayName: string): string;
|
|
31
|
-
/** Host path of the CA that signs everything the gateway intercepts; dimensions behind it must trust it. */
|
|
32
|
-
export declare function gatewayCaCertificatePath(stateDirectory: string): string;
|
|
33
8
|
export declare function assertValidName(kind: string, name: string): void;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*/
|
|
38
|
-
export declare function createGatewayService(storage: GatewayStorage, portals: PortalStorage, docker: DockerClient, image: ManagedImage, host: Sandbox): GatewayService;
|
|
9
|
+
export declare function createGatewayService(host: Sandbox & SandboxDataEndpoint, { dataDirectory }?: {
|
|
10
|
+
dataDirectory?: string;
|
|
11
|
+
}): GatewayService;
|
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
import { isIPv4 } from "node:net";
|
|
2
|
-
import {
|
|
2
|
+
import { createDockerClient } from "../lib/docker.js";
|
|
3
|
+
import { createGatewayImage } from "./image.js";
|
|
3
4
|
import { InvalidNameError, checkName } from "../lib/jsonDirectory.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { HYPERBRANE_VERSION } from "../lib/version.js";
|
|
7
|
-
import { GatewayConflictError, GatewayInvalidError, GatewayNotFoundError, } from "./api.js";
|
|
8
|
-
import { issueKeyFake } from "./fakes.js";
|
|
5
|
+
import { GatewayInvalidError, GatewayNotFoundError } from "./api.js";
|
|
6
|
+
import { GATEWAY_STATE_PATH, gatewayCaCertificatePath, gatewayContainerName, gatewayControl } from "./control.js";
|
|
9
7
|
import { BUILTIN_UPSTREAMS } from "../upstreams/index.js";
|
|
10
|
-
|
|
11
|
-
export const GATEWAY_STATE_PATH = "/state";
|
|
12
|
-
const PROXY_PORT = 8080;
|
|
13
|
-
const READY_TIMEOUT_MS = 60_000;
|
|
14
|
-
// "hybgw-" can't collide with a dimension's "hyb-<name>": dimension names start with a letter or digit.
|
|
15
|
-
export function gatewayContainerName(gatewayName) {
|
|
16
|
-
return `hybgw-${gatewayName}`;
|
|
17
|
-
}
|
|
18
|
-
/** Host path of the CA that signs everything the gateway intercepts; dimensions behind it must trust it. */
|
|
19
|
-
export function gatewayCaCertificatePath(stateDirectory) {
|
|
20
|
-
return `${stateDirectory}/mitmproxy/mitmproxy-ca-cert.pem`;
|
|
21
|
-
}
|
|
8
|
+
export { GATEWAY_STATE_PATH, gatewayCaCertificatePath, gatewayContainerName };
|
|
22
9
|
export function assertValidName(kind, name) {
|
|
23
10
|
try {
|
|
24
11
|
checkName(name);
|
|
@@ -29,170 +16,51 @@ export function assertValidName(kind, name) {
|
|
|
29
16
|
throw error;
|
|
30
17
|
}
|
|
31
18
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export function createGatewayService(
|
|
37
|
-
|
|
38
|
-
// visible, and every later step checks before it acts, so re-running converges.
|
|
19
|
+
const FAKE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
20
|
+
function endpointName(gatewayName) {
|
|
21
|
+
return `gateway-${gatewayName}`;
|
|
22
|
+
}
|
|
23
|
+
export function createGatewayService(host, { dataDirectory } = {}) {
|
|
24
|
+
const control = gatewayControl(host, () => createGatewayImage(createDockerClient(host)).ensure(), { dataDirectory });
|
|
39
25
|
async function createGateway(gateway) {
|
|
40
26
|
assertValidName("gateway", gateway.name);
|
|
41
27
|
const upstreams = (gateway.upstreams ?? BUILTIN_UPSTREAMS).map(validUpstream);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (existing)
|
|
45
|
-
assertOwnedContainer(existing, gateway.name);
|
|
46
|
-
const record = await storage.insertGateway({ name: gateway.name, state: "creating" });
|
|
47
|
-
const stateDirectory = await storage.ensureStateDirectory(gateway.name);
|
|
48
|
-
for (const upstream of upstreams)
|
|
49
|
-
await storage.saveUpstream(gateway.name, upstream);
|
|
50
|
-
const imageTag = await image.ensure();
|
|
51
|
-
await ensureContainer(gateway.name, stateDirectory, imageTag);
|
|
52
|
-
await docker.startContainer(name);
|
|
53
|
-
await awaitReady(gateway.name, stateDirectory);
|
|
54
|
-
if (record.state !== "ready")
|
|
55
|
-
await storage.saveGateway({ name: gateway.name, state: "ready" });
|
|
28
|
+
await control.createGateway(gateway.name, upstreams);
|
|
29
|
+
await control.startTransport(gateway.name, await host.openEndpoint(endpointName(gateway.name)), { restart: false });
|
|
56
30
|
return { name: gateway.name };
|
|
57
31
|
}
|
|
58
|
-
// A container from an older image is replaced: everything worth keeping (CA, credentials, rules)
|
|
59
|
-
// is in the mounted state directory. Its portals are re-wired by the portal watcher, or by the
|
|
60
|
-
// restore every command runs first.
|
|
61
|
-
async function ensureContainer(gatewayName, stateDirectory, imageTag) {
|
|
62
|
-
const name = gatewayContainerName(gatewayName);
|
|
63
|
-
const existing = await docker.inspectContainer(name);
|
|
64
|
-
if (existing) {
|
|
65
|
-
assertOwnedContainer(existing, gatewayName);
|
|
66
|
-
if (existing.Config?.Image === imageTag)
|
|
67
|
-
return;
|
|
68
|
-
await docker.removeContainer(name);
|
|
69
|
-
}
|
|
70
|
-
try {
|
|
71
|
-
await docker.createContainer(name, {
|
|
72
|
-
Image: imageTag,
|
|
73
|
-
Hostname: name,
|
|
74
|
-
Labels: {
|
|
75
|
-
hyperbrane: "true",
|
|
76
|
-
"hyperbrane.version": HYPERBRANE_VERSION,
|
|
77
|
-
"hyperbrane.gateway": gatewayName,
|
|
78
|
-
},
|
|
79
|
-
HostConfig: {
|
|
80
|
-
// A mount, not a copy: rules and credentials written by the service take effect on the next
|
|
81
|
-
// request, and the CA survives the container being recreated.
|
|
82
|
-
Binds: [`${stateDirectory}:${GATEWAY_STATE_PATH}`],
|
|
83
|
-
CapAdd: ["NET_ADMIN"],
|
|
84
|
-
NetworkMode: "bridge",
|
|
85
|
-
Init: true,
|
|
86
|
-
RestartPolicy: { Name: "unless-stopped" },
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
// Lost a race with another creator: fine as long as the winner is ours.
|
|
92
|
-
if (!(error instanceof DockerError && error.status === 409))
|
|
93
|
-
throw error;
|
|
94
|
-
assertOwnedContainer(await awaitContainer(name, error), gatewayName);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// Docker reserves the name before the winner's container becomes inspectable, so give it a moment.
|
|
98
|
-
async function awaitContainer(name, conflict) {
|
|
99
|
-
for (let attempt = 0; attempt < 50; attempt++) {
|
|
100
|
-
const container = await docker.inspectContainer(name);
|
|
101
|
-
if (container)
|
|
102
|
-
return container;
|
|
103
|
-
await sleep(100);
|
|
104
|
-
}
|
|
105
|
-
throw conflict;
|
|
106
|
-
}
|
|
107
|
-
// Ready = the proxy is listening (so the redirect rules are in) and the CA exists (so portals can
|
|
108
|
-
// install it into dimensions).
|
|
109
|
-
async function awaitReady(gatewayName, stateDirectory) {
|
|
110
|
-
const name = gatewayContainerName(gatewayName);
|
|
111
|
-
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
112
|
-
while (Date.now() < deadline) {
|
|
113
|
-
if ((await proxyListening(name)) && (await exists(gatewayCaCertificatePath(stateDirectory))))
|
|
114
|
-
return;
|
|
115
|
-
await sleep(250);
|
|
116
|
-
}
|
|
117
|
-
const state = (await docker.inspectContainer(name))?.State;
|
|
118
|
-
throw new Error(`gateway ${gatewayName} did not become ready: container ${state?.Status ?? "missing"}, exit code ${state?.ExitCode ?? "-"}`);
|
|
119
|
-
}
|
|
120
|
-
async function proxyListening(name) {
|
|
121
|
-
try {
|
|
122
|
-
const result = await docker.exec(name, { cmd: ["ss", "-Hltn", `sport = :${PROXY_PORT}`], user: "root" });
|
|
123
|
-
return result.exitCode === 0 && result.stdout.trim() !== "";
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
// Not running (yet, or restarting after a failed start).
|
|
127
|
-
if (error instanceof DockerError && error.status === 409)
|
|
128
|
-
return false;
|
|
129
|
-
throw error;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
async function exists(path) {
|
|
133
|
-
try {
|
|
134
|
-
await host.stat(path);
|
|
135
|
-
return true;
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
if (error instanceof SandboxNotFoundError)
|
|
139
|
-
return false;
|
|
140
|
-
throw error;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
// Container first: if this crashes before the record is removed, the gateway still shows up and
|
|
144
|
-
// the destroy can be retried. Its state (credentials included) goes with the record.
|
|
145
32
|
async function destroyGateway(gatewayName) {
|
|
146
33
|
assertValidName("gateway", gatewayName);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
throw new GatewayConflictError(`gateway ${gatewayName} still has portals: ${attached.map((portal) => portal.name).join(", ")}`);
|
|
150
|
-
}
|
|
151
|
-
const name = gatewayContainerName(gatewayName);
|
|
152
|
-
const existing = await docker.inspectContainer(name);
|
|
153
|
-
if (existing) {
|
|
154
|
-
assertOwnedContainer(existing, gatewayName);
|
|
155
|
-
await docker.removeContainer(name);
|
|
156
|
-
}
|
|
157
|
-
await storage.removeGateway(gatewayName);
|
|
34
|
+
await control.destroyGateway(gatewayName);
|
|
35
|
+
await host.closeEndpoint(endpointName(gatewayName));
|
|
158
36
|
}
|
|
159
37
|
async function restartGateway(gatewayName) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (!container)
|
|
164
|
-
throw new GatewayNotFoundError(`gateway ${gatewayName} has no container; create it again`);
|
|
165
|
-
assertOwnedContainer(container, gatewayName);
|
|
166
|
-
await docker.restartContainer(name);
|
|
167
|
-
await awaitReady(gatewayName, await storage.ensureStateDirectory(record.name));
|
|
38
|
+
assertValidName("gateway", gatewayName);
|
|
39
|
+
await control.restartGateway(gatewayName);
|
|
40
|
+
await control.startTransport(gatewayName, await host.openEndpoint(endpointName(gatewayName)), { restart: true });
|
|
168
41
|
}
|
|
169
|
-
async function
|
|
170
|
-
|
|
42
|
+
async function endpoint(gatewayName, options) {
|
|
43
|
+
assertValidName("gateway", gatewayName);
|
|
44
|
+
const name = endpointName(gatewayName);
|
|
45
|
+
const found = (await host.listEndpoints()).find((candidate) => candidate.name === name);
|
|
46
|
+
if (!found)
|
|
47
|
+
throw new GatewayNotFoundError(`gateway ${gatewayName} has no data endpoint; create it again`);
|
|
48
|
+
return { url: found.url, credentials: await host.credentials(name, options) };
|
|
171
49
|
}
|
|
172
50
|
async function listCredentials(gatewayName) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (held.get(`${upstream.name}.oauth`))
|
|
179
|
-
credentials.push({ name: `${upstream.name}.oauth`, gatewayName, type: "oauth" });
|
|
180
|
-
const apiKeys = held.get(`${upstream.name}.api-keys`);
|
|
181
|
-
for (const [keyName, { fake }] of Object.entries(apiKeys?.keys ?? {})) {
|
|
182
|
-
credentials.push({ name: `${upstream.name}.key.${keyName}`, gatewayName, type: "apiKey", fake });
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return credentials;
|
|
51
|
+
assertValidName("gateway", gatewayName);
|
|
52
|
+
return (await control.listCredentials(gatewayName)).flatMap(({ upstream, oauth, apiKeys }) => [
|
|
53
|
+
...(oauth ? [{ name: `${upstream}.oauth`, gatewayName, type: "oauth" }] : []),
|
|
54
|
+
...Object.entries(apiKeys?.keys ?? {}).map(([keyName, { fake }]) => ({ name: `${upstream}.key.${keyName}`, gatewayName, type: "apiKey", fake })),
|
|
55
|
+
]);
|
|
186
56
|
}
|
|
187
|
-
// Storage holds the only copy of a secret, and the gateway re-reads credentials per request. Without
|
|
188
|
-
// its OAuth credential, the upstream's next sign-in goes to the upstream again (switching accounts).
|
|
189
57
|
async function deleteCredential(gatewayName, credentialName) {
|
|
190
58
|
assertValidName("gateway", gatewayName);
|
|
191
59
|
const keyAt = credentialName.indexOf(".key.");
|
|
192
60
|
if (credentialName.endsWith(".oauth")) {
|
|
193
61
|
const upstreamName = credentialName.slice(0, -".oauth".length);
|
|
194
62
|
assertValidName("upstream", upstreamName);
|
|
195
|
-
await
|
|
63
|
+
await control.removeOAuthCredential(gatewayName, upstreamName);
|
|
196
64
|
}
|
|
197
65
|
else if (keyAt > 0) {
|
|
198
66
|
await deleteApiKey(gatewayName, credentialName.slice(0, keyAt), credentialName.slice(keyAt + ".key.".length));
|
|
@@ -202,134 +70,99 @@ export function createGatewayService(storage, portals, docker, image, host) {
|
|
|
202
70
|
}
|
|
203
71
|
}
|
|
204
72
|
async function registerUpstream(gatewayName, upstream) {
|
|
205
|
-
|
|
73
|
+
assertValidName("gateway", gatewayName);
|
|
206
74
|
const definition = validUpstream(upstream);
|
|
207
|
-
await
|
|
75
|
+
await control.registerUpstream(gatewayName, definition);
|
|
208
76
|
return definition;
|
|
209
77
|
}
|
|
210
78
|
async function listUpstreams(gatewayName) {
|
|
211
|
-
|
|
212
|
-
return (await
|
|
79
|
+
assertValidName("gateway", gatewayName);
|
|
80
|
+
return (await control.listUpstreams(gatewayName)).sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
213
81
|
}
|
|
214
82
|
async function removeUpstream(gatewayName, upstreamName) {
|
|
215
83
|
assertValidName("gateway", gatewayName);
|
|
216
84
|
assertValidName("upstream", upstreamName);
|
|
217
|
-
await
|
|
85
|
+
await control.removeUpstream(gatewayName, upstreamName);
|
|
218
86
|
}
|
|
219
|
-
// A key keeps its fake when replaced, so dimensions already holding it keep working.
|
|
220
87
|
async function setApiKey(gatewayName, upstreamName, keyName, key) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
throw new GatewayInvalidError(`upstream ${upstreamName} has no API key mode`);
|
|
88
|
+
assertValidName("gateway", gatewayName);
|
|
89
|
+
assertValidName("upstream", upstreamName);
|
|
224
90
|
assertValidName("API key", keyName);
|
|
225
91
|
if (typeof key !== "string" || key === "")
|
|
226
92
|
throw new GatewayInvalidError("the API key is empty");
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
await
|
|
230
|
-
return { fake };
|
|
93
|
+
const bytes = crypto.getRandomValues(new Uint8Array(key.length + 16));
|
|
94
|
+
const characters = Array.from(bytes, (byte) => FAKE_ALPHABET[byte % FAKE_ALPHABET.length]).join("");
|
|
95
|
+
return { fake: await control.setApiKey(gatewayName, upstreamName, keyName, key, characters) };
|
|
231
96
|
}
|
|
232
97
|
async function deleteApiKey(gatewayName, upstreamName, keyName) {
|
|
233
|
-
|
|
98
|
+
assertValidName("gateway", gatewayName);
|
|
99
|
+
assertValidName("upstream", upstreamName);
|
|
234
100
|
assertValidName("API key", keyName);
|
|
235
|
-
|
|
236
|
-
if (!stored?.keys[keyName])
|
|
237
|
-
return;
|
|
238
|
-
const { [keyName]: _removed, ...keys } = stored.keys;
|
|
239
|
-
if (Object.keys(keys).length === 0)
|
|
240
|
-
await storage.removeApiKeys(gatewayName, upstreamName);
|
|
241
|
-
else
|
|
242
|
-
await storage.saveApiKeys(gatewayName, upstreamName, { keys });
|
|
101
|
+
await control.deleteApiKey(gatewayName, upstreamName, keyName);
|
|
243
102
|
}
|
|
244
103
|
async function createTrafficRule(gatewayName, rule) {
|
|
245
|
-
|
|
104
|
+
assertValidName("gateway", gatewayName);
|
|
246
105
|
const requested = validTrafficRule(rule);
|
|
247
|
-
|
|
248
|
-
if (!sameTrafficRule(stored, requested)) {
|
|
249
|
-
throw new GatewayConflictError(`traffic rule ${rule.name} already exists with a different spec`);
|
|
250
|
-
}
|
|
106
|
+
await control.createTrafficRule(gatewayName, requested);
|
|
251
107
|
return requested;
|
|
252
108
|
}
|
|
253
109
|
async function updateTrafficRule(gatewayName, rule) {
|
|
254
|
-
|
|
110
|
+
assertValidName("gateway", gatewayName);
|
|
255
111
|
const requested = validTrafficRule(rule);
|
|
256
|
-
await
|
|
257
|
-
await storage.saveTrafficRule(gatewayName, requested);
|
|
112
|
+
await control.updateTrafficRule(gatewayName, requested);
|
|
258
113
|
return requested;
|
|
259
114
|
}
|
|
260
|
-
// Requests an ASK rule is holding carry on once it's gone.
|
|
261
115
|
async function deleteTrafficRule(gatewayName, ruleName) {
|
|
262
116
|
assertValidName("gateway", gatewayName);
|
|
263
117
|
assertValidName("traffic rule", ruleName);
|
|
264
|
-
await
|
|
118
|
+
await control.deleteTrafficRule(gatewayName, ruleName);
|
|
265
119
|
}
|
|
266
120
|
async function listTrafficRules(gatewayName) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
return rules.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
121
|
+
assertValidName("gateway", gatewayName);
|
|
122
|
+
return (await control.listTrafficRules(gatewayName)).sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
270
123
|
}
|
|
271
|
-
// Answers every request the rule is holding right now; later requests wait for a later answer.
|
|
272
124
|
async function trafficRuleRespond(gatewayName, ruleName, action) {
|
|
273
|
-
await requireGateway(gatewayName);
|
|
274
|
-
if (action !== "ALLOW" && action !== "DENY")
|
|
275
|
-
throw new GatewayInvalidError(`invalid response: ${action}`);
|
|
276
|
-
const rule = await requireTrafficRule(gatewayName, ruleName);
|
|
277
|
-
if (rule.action !== "ASK")
|
|
278
|
-
throw new GatewayInvalidError(`traffic rule ${ruleName} is not an ASK rule`);
|
|
279
|
-
await storage.saveTrafficRuleResponse(gatewayName, { name: ruleName, action, at: Date.now() });
|
|
280
|
-
}
|
|
281
|
-
async function requireGateway(gatewayName) {
|
|
282
125
|
assertValidName("gateway", gatewayName);
|
|
283
|
-
const record = await storage.readGateway(gatewayName);
|
|
284
|
-
if (!record)
|
|
285
|
-
throw new GatewayNotFoundError(`gateway ${gatewayName} does not exist`);
|
|
286
|
-
return record;
|
|
287
|
-
}
|
|
288
|
-
async function requireUpstream(gatewayName, upstreamName) {
|
|
289
|
-
await requireGateway(gatewayName);
|
|
290
|
-
assertValidName("upstream", upstreamName);
|
|
291
|
-
const upstream = await storage.readUpstream(gatewayName, upstreamName);
|
|
292
|
-
if (!upstream)
|
|
293
|
-
throw new GatewayNotFoundError(`upstream ${upstreamName} does not exist on gateway ${gatewayName}`);
|
|
294
|
-
return upstream;
|
|
295
|
-
}
|
|
296
|
-
async function requireTrafficRule(gatewayName, ruleName) {
|
|
297
126
|
assertValidName("traffic rule", ruleName);
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return rule;
|
|
127
|
+
if (action !== "ALLOW" && action !== "DENY")
|
|
128
|
+
throw new GatewayInvalidError(`invalid response: ${action}`);
|
|
129
|
+
await control.trafficRuleRespond(gatewayName, ruleName, action);
|
|
302
130
|
}
|
|
303
131
|
return {
|
|
304
|
-
createGateway,
|
|
305
|
-
destroyGateway,
|
|
306
|
-
listGateways,
|
|
307
|
-
restartGateway,
|
|
132
|
+
createGateway: (gateway) => createGateway(gateway),
|
|
133
|
+
destroyGateway: (gatewayName) => destroyGateway(gatewayName),
|
|
134
|
+
listGateways: () => control.listGateways(),
|
|
135
|
+
restartGateway: (gatewayName) => restartGateway(gatewayName),
|
|
136
|
+
endpoint,
|
|
308
137
|
listCredentials,
|
|
309
|
-
deleteCredential,
|
|
310
|
-
registerUpstream,
|
|
138
|
+
deleteCredential: (gatewayName, credentialName) => deleteCredential(gatewayName, credentialName),
|
|
139
|
+
registerUpstream: (gatewayName, upstream) => registerUpstream(gatewayName, upstream),
|
|
311
140
|
listUpstreams,
|
|
312
|
-
removeUpstream,
|
|
313
|
-
setApiKey,
|
|
314
|
-
deleteApiKey,
|
|
315
|
-
createTrafficRule,
|
|
316
|
-
updateTrafficRule,
|
|
317
|
-
deleteTrafficRule,
|
|
141
|
+
removeUpstream: (gatewayName, upstreamName) => removeUpstream(gatewayName, upstreamName),
|
|
142
|
+
setApiKey: (gatewayName, upstreamName, keyName, key) => setApiKey(gatewayName, upstreamName, keyName, key),
|
|
143
|
+
deleteApiKey: (gatewayName, upstreamName, keyName) => deleteApiKey(gatewayName, upstreamName, keyName),
|
|
144
|
+
createTrafficRule: (gatewayName, rule) => createTrafficRule(gatewayName, rule),
|
|
145
|
+
updateTrafficRule: (gatewayName, rule) => updateTrafficRule(gatewayName, rule),
|
|
146
|
+
deleteTrafficRule: (gatewayName, ruleName) => deleteTrafficRule(gatewayName, ruleName),
|
|
318
147
|
listTrafficRules,
|
|
319
|
-
trafficRuleRespond,
|
|
148
|
+
trafficRuleRespond: (gatewayName, ruleName, action) => trafficRuleRespond(gatewayName, ruleName, action),
|
|
320
149
|
};
|
|
321
150
|
}
|
|
322
|
-
/** The checks the gateway relies on; the rest of the shape is the SDK client's (see upstream.ts). */
|
|
323
151
|
function validUpstream(upstream) {
|
|
324
152
|
assertValidName("upstream", upstream.name);
|
|
325
|
-
const { oauth, apiKey } = upstream.modes ?? {};
|
|
326
|
-
if (!oauth && !apiKey)
|
|
327
|
-
throw new GatewayInvalidError(`upstream ${upstream.name} needs an oauth or
|
|
153
|
+
const { oauth, apiKey, forced } = upstream.modes ?? {};
|
|
154
|
+
if (!oauth && !apiKey && !forced)
|
|
155
|
+
throw new GatewayInvalidError(`upstream ${upstream.name} needs an oauth, apiKey or forced mode`);
|
|
156
|
+
for (const mode of [oauth, apiKey, forced]) {
|
|
157
|
+
if (mode && (!Array.isArray(mode.hosts) || mode.hosts.length === 0))
|
|
158
|
+
throw new GatewayInvalidError(`upstream ${upstream.name}: every mode needs hosts`);
|
|
159
|
+
}
|
|
328
160
|
for (const mode of [oauth, apiKey]) {
|
|
329
|
-
if (mode &&
|
|
330
|
-
throw new GatewayInvalidError(`upstream ${upstream.name}:
|
|
331
|
-
}
|
|
161
|
+
if (mode && !mode.present)
|
|
162
|
+
throw new GatewayInvalidError(`upstream ${upstream.name}: oauth and apiKey modes need present`);
|
|
332
163
|
}
|
|
164
|
+
if (forced && !forced.force)
|
|
165
|
+
throw new GatewayInvalidError(`upstream ${upstream.name}: a forced mode needs force`);
|
|
333
166
|
if (oauth && (!oauth.tokenUrl || !oauth.fakes?.access)) {
|
|
334
167
|
throw new GatewayInvalidError(`upstream ${upstream.name}: oauth needs tokenUrl and fakes.access`);
|
|
335
168
|
}
|
|
@@ -337,7 +170,6 @@ function validUpstream(upstream) {
|
|
|
337
170
|
throw new GatewayInvalidError(`upstream ${upstream.name}: apiKey needs a fake shape`);
|
|
338
171
|
return upstream;
|
|
339
172
|
}
|
|
340
|
-
/** Returns just the rule's fields, so nothing unknown ends up in storage. */
|
|
341
173
|
function validTrafficRule(rule) {
|
|
342
174
|
assertValidName("traffic rule", rule.name);
|
|
343
175
|
if (typeof rule.urlMask !== "string" || rule.urlMask === "") {
|
|
@@ -356,7 +188,6 @@ function validTrafficRule(rule) {
|
|
|
356
188
|
return { name: rule.name, urlMask: rule.urlMask, action: rule.action, delayMs: rule.delayMs };
|
|
357
189
|
}
|
|
358
190
|
const TCP_SCHEME = "tcp://";
|
|
359
|
-
/** "tcp://<address>:<port>": address is "*", an IPv4 address or a CIDR; port is "*" or a number. */
|
|
360
191
|
function assertValidTcpMask(ruleName, urlMask) {
|
|
361
192
|
const target = urlMask.slice(TCP_SCHEME.length);
|
|
362
193
|
const separator = target.lastIndexOf(":");
|
|
@@ -373,8 +204,3 @@ function assertValidTcpMask(ruleName, urlMask) {
|
|
|
373
204
|
function sameTrafficRule(a, b) {
|
|
374
205
|
return a.urlMask === b.urlMask && a.action === b.action && a.delayMs === b.delayMs;
|
|
375
206
|
}
|
|
376
|
-
function assertOwnedContainer(container, gatewayName) {
|
|
377
|
-
if (container.Config?.Labels?.["hyperbrane.gateway"] !== gatewayName) {
|
|
378
|
-
throw new GatewayConflictError(`container ${gatewayContainerName(gatewayName)} exists but is not managed by hyperbrane`);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { DockerClient } from "../lib/docker.ts";
|
|
2
2
|
import { type ManagedImage } from "../lib/image.ts";
|
|
3
|
-
|
|
4
|
-
export declare const GATEWAY_IMAGE_VERSION = "v16";
|
|
3
|
+
export declare const GATEWAY_IMAGE_VERSION = "v17";
|
|
5
4
|
export declare const GATEWAY_IMAGE_REPOSITORY = "hyperbrane-gateway";
|
|
6
5
|
export declare function createGatewayImage(docker: DockerClient): ManagedImage;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { createManagedImage } from "../lib/image.js";
|
|
2
|
-
// The files under ./image, as strings (see dimension/image.ts).
|
|
3
2
|
import { IMAGE_FILES } from "./imageFiles.generated.js";
|
|
4
|
-
|
|
5
|
-
export const GATEWAY_IMAGE_VERSION = "v16";
|
|
3
|
+
export const GATEWAY_IMAGE_VERSION = "v17";
|
|
6
4
|
export const GATEWAY_IMAGE_REPOSITORY = "hyperbrane-gateway";
|
|
7
5
|
export function createGatewayImage(docker) {
|
|
8
6
|
return createManagedImage(docker, {
|