import * as NodeCrypto from "node:crypto";import { AuthRelayReadScope, AuthRelayWriteScope, AuthStandardClientScopes, EnvironmentCloudEndpointUnavailableError, EnvironmentCloudLinkStateResult, EnvironmentCloudRelayConfigResult, EnvironmentHttpApi, EnvironmentHttpBadRequestError, EnvironmentHttpConflictError, EnvironmentHttpInternalServerError, EnvironmentHttpUnauthorizedError,} from "@t3tools/contracts";import { RelayCloudEnvironmentHealthProofPayload, RelayCloudEnvironmentHealthRequest, RelayCloudMintCredentialProofPayload, RelayCloudMintCredentialRequest, RelayEnvironmentHealthResponseProofPayload, type RelayEnvironmentHealthResponse as RelayEnvironmentHealthResponseShape, RelayEnvironmentConfigRequest, RelayEnvironmentLinkChallengeResponse, RelayEnvironmentLinkResponse, RelayEnvironmentMintResponseProofPayload, type RelayEnvironmentMintResponse as RelayEnvironmentMintResponseShape, RelayEnvironmentLinkProof, RelayEnvironmentLinkProofPayload, RelayLinkProofRequest, RelayManagedEndpointOrigin,} from "@t3tools/contracts/relay";import { withRelayClientTracing } from "@t3tools/shared/relayTracing";import { normalizeRelayIssuer, RELAY_HEALTH_REQUEST_TYP, RELAY_HEALTH_RESPONSE_TYP, RELAY_LINK_PROOF_TYP, RELAY_MINT_REQUEST_TYP, RELAY_MINT_RESPONSE_TYP, signRelayJwt, verifyRelayJwt,} from "@t3tools/shared/relayJwt";import { isSecureRelayUrl } from "@t3tools/shared/relayUrl";import * as DateTime from "effect/DateTime";import * as Crypto from "effect/Crypto";import * as Duration from "effect/Duration";import * as Effect from "effect/Effect";import * as Option from "effect/Option";import * as Schema from "effect/Schema";import * as HttpEffect from "effect/unstable/http/HttpEffect";import * as HttpBody from "effect/unstable/http/HttpBody";import * as HttpClient from "effect/unstable/http/HttpClient";import * as HttpClientError from "effect/unstable/http/HttpClientError";import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder"; import * as EnvironmentAuth from "../auth/EnvironmentAuth.ts";import * as ServerSecretStore from "../auth/ServerSecretStore.ts";import { requireEnvironmentScope } from "../auth/http.ts";import * as ServerEnvironment from "../environment/ServerEnvironment.ts";import * as ManagedEndpointRuntime from "./ManagedEndpointRuntime.ts";import { CLOUD_ENDPOINT_RUNTIME_CONFIG, CLOUD_LINKED_USER_ID, CLOUD_MINT_PUBLIC_KEY, encodeEndpointRuntimeConfigJson, PUBLISH_AGENT_ACTIVITY_SECRET, RELAY_ENVIRONMENT_CREDENTIAL_SECRET, RELAY_ISSUER_SECRET, RELAY_URL_SECRET,} from "./config.ts";import { relayUrlConfig } from "./publicConfig.ts";import { setCliDesiredCloudLink } from "./CliState.ts";import * as CliTokenManager from "./CliTokenManager.ts";import { getOrCreateEnvironmentKeyPairFromSecretStore } from "./environmentKeys.ts";import { traceRelayRequest } from "./traceRelayRequest.ts"; const CLOUD_MINT_NONCE_PREFIX = "cloud-mint-nonce-";const CLOUD_MINT_JTI_PREFIX = "cloud-mint-jti-";const CLOUD_HEALTH_NONCE_PREFIX = "cloud-health-nonce-";const CLOUD_HEALTH_JTI_PREFIX = "cloud-health-jti-";const CLOUD_PROOF_MAX_LIFETIME_SECONDS = 5 * 60;const CLOUD_PROOF_CLOCK_SKEW_SECONDS = 60;const LOOPBACK_HOSTNAMES = new Set(["127.0.0.1", "::1", "localhost"]);const CLOUD_CREDENTIAL_RESPONSE_HEADERS = { "cache-control": "no-store", pragma: "no-cache",} as const; const CloudRelayRequestOperation = Schema.Literals([ "create-link-challenge", "create-environment-link",]); const CloudRelayRequestPhase = Schema.Literals([ "encode-request", "send-request", "check-response-status", "decode-response",]); export class CloudRelayConfigurationError extends Schema.TaggedErrorClass<CloudRelayConfigurationError>()( "CloudRelayConfigurationError", { configKey: Schema.Literal("T3CODE_RELAY_URL"), cause: Schema.Defect(), },) { override get message(): string { return `${this.configKey} must be configured as a secure absolute HTTPS origin.`; }} export class CloudRelayRequestError extends Schema.TaggedErrorClass<CloudRelayRequestError>()( "CloudRelayRequestError", { operation: CloudRelayRequestOperation, phase: CloudRelayRequestPhase, method: Schema.Literal("POST"), url: Schema.String, responseStatus: Schema.optional(Schema.Number), cause: Schema.Defect(), },) { static fromClientFailure(input: { readonly operation: CloudRelayRequestError["operation"]; readonly url: string; readonly cause: HttpBody.HttpBodyError | HttpClientError.HttpClientError | Schema.SchemaError; readonly responseStatus?: number; }): CloudRelayRequestError { if (input.cause._tag === "SchemaError") { return new CloudRelayRequestError({ operation: input.operation, phase: "decode-response", method: "POST", url: input.url, ...(input.responseStatus === undefined ? {} : { responseStatus: input.responseStatus }), cause: input.cause, }); } if (!HttpClientError.isHttpClientError(input.cause)) { return new CloudRelayRequestError({ operation: input.operation, phase: "encode-request", method: "POST", url: input.url, cause: input.cause, }); } const phase: CloudRelayRequestError["phase"] = (() => { switch (input.cause.reason._tag) { case "EncodeError": return "encode-request"; case "TransportError": case "InvalidUrlError": return "send-request"; case "StatusCodeError": return "check-response-status"; case "DecodeError": case "EmptyBodyError": return "decode-response"; } })(); return new CloudRelayRequestError({ operation: input.operation, phase, method: "POST", url: input.url, ...(input.cause.response === undefined ? input.responseStatus === undefined ? {} : { responseStatus: input.responseStatus } : { responseStatus: input.cause.response.status }), cause: input.cause, }); } override get message(): string { const responseStatus = this.responseStatus === undefined ? "" : ` with response status ${this.responseStatus}`; return `T3 Connect relay ${this.operation} failed during ${this.phase}${responseStatus}.`; }} const appendCloudCredentialResponseHeaders = HttpEffect.appendPreResponseHandler( (_request, response) => Effect.succeed(HttpServerResponse.setHeaders(response, CLOUD_CREDENTIAL_RESPONSE_HEADERS)),); const failEnvironmentCloudInternalError = (message: string) => (cause: unknown): Effect.Effect<never, EnvironmentHttpInternalServerError> => Effect.logError(message, { cause }).pipe( Effect.flatMap(() => Effect.fail(new EnvironmentHttpInternalServerError({ message }))), ); const requireRelayUrl = relayUrlConfig.pipe( Effect.mapError( (cause) => new CloudRelayConfigurationError({ configKey: "T3CODE_RELAY_URL", cause, }), ),); function bytesToString(bytes: Uint8Array): string { return new TextDecoder().decode(bytes);} function stringToBytes(value: string): Uint8Array { return new TextEncoder().encode(value);} export function consumeCloudReplayGuards(input: { readonly secrets: ServerSecretStore.ServerSecretStore["Service"]; readonly names: ReadonlyArray<string>; readonly value: Uint8Array;}) { return Effect.all( input.names.map((name) => input.secrets.create(name, input.value).pipe( Effect.as(true), Effect.catchTags({ SecretStorePersistError: (error) => ServerSecretStore.isSecretAlreadyExistsError(error) ? Effect.succeed(false) : Effect.fail(error), }), ), ), { concurrency: input.names.length }, ).pipe(Effect.map((created) => created.every(Boolean)));} function normalizePemForSignedPayload(value: string): string { return value.trim();} function normalizeHostname(hostname: string): string { return hostname .trim() .toLowerCase() .replace(/^\[(.*)\]$/, "$1");} function validateCloudMintPublicKey( publicKey: string,): Effect.Effect<void, EnvironmentHttpBadRequestError> { return Effect.try({ try: () => NodeCrypto.createPublicKey(publicKey.replace(/\\n/g, "\n")), catch: () => new EnvironmentHttpBadRequestError({ message: "Cloud mint public key must be a valid Ed25519 public key.", }), }).pipe( Effect.flatMap((key) => key.asymmetricKeyType === "ed25519" ? Effect.void : Effect.fail( new EnvironmentHttpBadRequestError({ message: "Cloud mint public key must be a valid Ed25519 public key.", }), ), ), );} function validateRelayConfigPayload( payload: RelayEnvironmentConfigRequest,): Effect.Effect<void, EnvironmentHttpBadRequestError> { if (!isSecureRelayUrl(payload.relayUrl)) { return Effect.fail( new EnvironmentHttpBadRequestError({ message: "Relay URL must be a secure absolute HTTPS URL.", }), ); } if (payload.relayIssuer !== undefined && !isSecureRelayUrl(payload.relayIssuer)) { return Effect.fail( new EnvironmentHttpBadRequestError({ message: "Relay issuer must be a secure absolute HTTPS URL.", }), ); } if (payload.environmentCredential.trim().length === 0) { return Effect.fail( new EnvironmentHttpBadRequestError({ message: "Relay environment credential is required.", }), ); } if (payload.cloudUserId.trim().length === 0) { return Effect.fail( new EnvironmentHttpBadRequestError({ message: "Cloud user id is required.", }), ); } return Effect.void;} function validateLinkedCloudUser(input: { readonly secrets: ServerSecretStore.ServerSecretStore["Service"]; readonly cloudUserId: string;}) { return input.secrets.get(CLOUD_LINKED_USER_ID).pipe( Effect.mapError( (cause) => new EnvironmentAuth.ServerAuthLinkedCloudAccountVerificationError({ cause, }), ), Effect.flatMap((existing) => { if (Option.isNone(existing)) { return Effect.void; } const existingCloudUserId = bytesToString(existing.value); return existingCloudUserId === input.cloudUserId ? Effect.void : Effect.fail( new EnvironmentHttpConflictError({ message: "This environment is already linked to a different cloud account. Unlink it before switching accounts.", }), ); }), );} function readInstalledCloudUserId(secrets: ServerSecretStore.ServerSecretStore["Service"]) { return secrets.get(CLOUD_LINKED_USER_ID).pipe( Effect.mapError( (cause) => new EnvironmentAuth.ServerAuthLinkedCloudAccountReadError({ cause, }), ), Effect.flatMap((bytes) => Option.isSome(bytes) ? Effect.succeed(bytesToString(bytes.value)) : Effect.fail(new EnvironmentAuth.ServerAuthLinkedCloudAccountMissingError({})), ), );} function isLoopbackHostname(hostname: string): boolean { return LOOPBACK_HOSTNAMES.has(normalizeHostname(hostname));} function firstForwardedHeaderValue(value: string | undefined): string | undefined { const first = value?.split(",")[0]?.trim(); return first && first.length > 0 ? first : undefined;} function requestAbsoluteUrl(request: HttpServerRequest.HttpServerRequest): string | null { try { return new URL(request.originalUrl).href; } catch { const host = firstForwardedHeaderValue(request.headers.host) ?? "127.0.0.1"; try { return new URL(request.originalUrl, `http://${host}`).href; } catch { return null; } }} function hasForwardedAuthorityHeaders(request: HttpServerRequest.HttpServerRequest): boolean { return ( firstForwardedHeaderValue(request.headers["x-forwarded-host"]) !== undefined || firstForwardedHeaderValue(request.headers["x-forwarded-proto"]) !== undefined );} function endpointRequestPort(url: URL): number { return Number(url.port || (url.protocol === "https:" ? 443 : 80));} function isAllowedEndpointOrigin(input: { readonly origin: RelayManagedEndpointOrigin; readonly requestUrl: string;}): boolean { if (!isLoopbackHostname(input.origin.localHttpHost)) { return false; } const url = new URL(input.requestUrl); if (!isLoopbackHostname(url.hostname)) { return false; } return input.origin.localHttpPort === endpointRequestPort(url);} function providerKindMatchesRequestedLinkScopes(request: RelayLinkProofRequest): boolean { return request.endpoint.providerKind === "cloudflare_tunnel";} function hasExactScope(input: { readonly scopes: ReadonlyArray<string>; readonly expected: string;}): boolean { return input.scopes.length === 1 && input.scopes[0] === input.expected;} function hasBoundedCloudProofLifetime(input: { readonly iat: number; readonly exp: number; readonly nowSeconds: number;}): boolean { return ( input.exp > input.iat && input.exp - input.iat <= CLOUD_PROOF_MAX_LIFETIME_SECONDS && input.iat <= input.nowSeconds + CLOUD_PROOF_CLOCK_SKEW_SECONDS );} const decodeCloudHealthProof = Schema.decodeUnknownEffect(RelayCloudEnvironmentHealthProofPayload);const decodeCloudMintProof = Schema.decodeUnknownEffect(RelayCloudMintCredentialProofPayload); interface CloudHttpDependencies { readonly secrets: ServerSecretStore.ServerSecretStore["Service"]; readonly environment: ServerEnvironment.ServerEnvironment["Service"]; readonly endpointRuntime: ManagedEndpointRuntime.CloudManagedEndpointRuntime["Service"]; readonly environmentAuth: EnvironmentAuth.EnvironmentAuth["Service"]; readonly cliTokenManager: CliTokenManager.CloudCliTokenManager["Service"]; readonly httpClient: HttpClient.HttpClient;} const cloudHttpDependencies = Effect.gen(function* () { return { secrets: yield* ServerSecretStore.ServerSecretStore, environment: yield* ServerEnvironment.ServerEnvironment, endpointRuntime: yield* ManagedEndpointRuntime.CloudManagedEndpointRuntime, environmentAuth: yield* EnvironmentAuth.EnvironmentAuth, cliTokenManager: yield* CliTokenManager.CloudCliTokenManager, httpClient: yield* HttpClient.HttpClient, } satisfies CloudHttpDependencies;}); const makeCloudLinkProof = Effect.fn("environment.cloud.makeLinkProof")(function* ( dependencies: CloudHttpDependencies, request: RelayLinkProofRequest, requestUrl: string,) { const keyPair = yield* getOrCreateEnvironmentKeyPairFromSecretStore(dependencies.secrets); if ( !providerKindMatchesRequestedLinkScopes(request) || !isAllowedEndpointOrigin({ origin: request.origin, requestUrl, }) ) { return yield* new EnvironmentHttpBadRequestError({ message: "Invalid managed endpoint origin.", }); } const now = yield* DateTime.now; const expiresAt = DateTime.add(now, { minutes: 5 }); const nowSeconds = Math.floor(now.epochMilliseconds / 1_000); const descriptor = yield* dependencies.environment.getDescriptor; const payload = { iss: `t3-env:${descriptor.environmentId}`, aud: normalizeRelayIssuer(request.relayIssuer), sub: descriptor.environmentId, jti: yield* Crypto.Crypto.pipe(Effect.flatMap((crypto) => crypto.randomUUIDv4)), iat: nowSeconds, exp: Math.floor(expiresAt.epochMilliseconds / 1_000), challenge: request.challenge, descriptor, environmentId: descriptor.environmentId, environmentPublicKey: normalizePemForSignedPayload(keyPair.publicKey), endpoint: request.endpoint, origin: request.origin, scopes: ["agent_activity_notifications", "managed_tunnels"], } satisfies RelayEnvironmentLinkProofPayload; return yield* signRelayJwt({ privateKey: keyPair.privateKey, typ: RELAY_LINK_PROOF_TYP, payload, }).pipe( Effect.mapError( (cause) => new EnvironmentAuth.ServerAuthCloudLinkJwtSigningError({ cause, }), ), );}); const cloudLinkProofHandler = Effect.fn("environment.cloud.linkProof")( function* (dependencies: CloudHttpDependencies, request: RelayLinkProofRequest) { yield* requireEnvironmentScope(AuthRelayWriteScope);Lines 1–500 of 1170. Load more
import * as NodeCrypto from "node:crypto"; import { AuthRelayReadScope, AuthRelayWriteScope, AuthStandardClientScopes, EnvironmentCloudEndpointUnavailableError, EnvironmentCloudLinkStateResult, EnvironmentCloudRelayConfigResult, EnvironmentHttpApi, EnvironmentHttpBadRequestError, EnvironmentHttpConflictError, EnvironmentHttpInternalServerError, EnvironmentHttpUnauthorizedError, } from "@t3tools/contracts"; import { RelayCloudEnvironmentHealthProofPayload, RelayCloudEnvironmentHealthRequest, RelayCloudMintCredentialProofPayload, RelayCloudMintCredentialRequest, RelayEnvironmentHealthResponseProofPayload, type RelayEnvironmentHealthResponse as RelayEnvironmentHealthResponseShape, RelayEnvironmentConfigRequest, RelayEnvironmentLinkChallengeResponse, RelayEnvironmentLinkResponse, RelayEnvironmentMintResponseProofPayload, type RelayEnvironmentMintResponse as RelayEnvironmentMintResponseShape, RelayEnvironmentLinkProof, RelayEnvironmentLinkProofPayload, RelayLinkProofRequest, RelayManagedEndpointOrigin, } from "@t3tools/contracts/relay"; import { withRelayClientTracing } from "@t3tools/shared/relayTracing"; import { normalizeRelayIssuer, RELAY_HEALTH_REQUEST_TYP, RELAY_HEALTH_RESPONSE_TYP, RELAY_LINK_PROOF_TYP, RELAY_MINT_REQUEST_TYP, RELAY_MINT_RESPONSE_TYP, signRelayJwt, verifyRelayJwt, } from "@t3tools/shared/relayJwt"; import { isSecureRelayUrl } from "@t3tools/shared/relayUrl"; import * as DateTime from "effect/DateTime"; import * as Crypto from "effect/Crypto"; import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as HttpEffect from "effect/unstable/http/HttpEffect"; import * as HttpBody from "effect/unstable/http/HttpBody"; import * as HttpClient from "effect/unstable/http/HttpClient"; import * as HttpClientError from "effect/unstable/http/HttpClientError"; import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"; import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"; import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest"; import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse"; import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder"; import * as EnvironmentAuth from "../auth/EnvironmentAuth.ts"; import * as ServerSecretStore from "../auth/ServerSecretStore.ts"; import { requireEnvironmentScope } from "../auth/http.ts"; import * as ServerEnvironment from "../environment/ServerEnvironment.ts"; import * as ManagedEndpointRuntime from "./ManagedEndpointRuntime.ts"; import { CLOUD_ENDPOINT_RUNTIME_CONFIG, CLOUD_LINKED_USER_ID, CLOUD_MINT_PUBLIC_KEY, encodeEndpointRuntimeConfigJson, PUBLISH_AGENT_ACTIVITY_SECRET, RELAY_ENVIRONMENT_CREDENTIAL_SECRET, RELAY_ISSUER_SECRET, RELAY_URL_SECRET, } from "./config.ts"; import { relayUrlConfig } from "./publicConfig.ts"; import { setCliDesiredCloudLink } from "./CliState.ts"; import * as CliTokenManager from "./CliTokenManager.ts"; import { getOrCreateEnvironmentKeyPairFromSecretStore } from "./environmentKeys.ts"; import { traceRelayRequest } from "./traceRelayRequest.ts"; const CLOUD_MINT_NONCE_PREFIX = "cloud-mint-nonce-"; const CLOUD_MINT_JTI_PREFIX = "cloud-mint-jti-"; const CLOUD_HEALTH_NONCE_PREFIX = "cloud-health-nonce-"; const CLOUD_HEALTH_JTI_PREFIX = "cloud-health-jti-"; const CLOUD_PROOF_MAX_LIFETIME_SECONDS = 5 * 60; const CLOUD_PROOF_CLOCK_SKEW_SECONDS = 60; const LOOPBACK_HOSTNAMES = new Set(["127.0.0.1", "::1", "localhost"]); const CLOUD_CREDENTIAL_RESPONSE_HEADERS = { "cache-control": "no-store", pragma: "no-cache", } as const; const CloudRelayRequestOperation = Schema.Literals([ "create-link-challenge", "create-environment-link", ]); const CloudRelayRequestPhase = Schema.Literals([ "encode-request", "send-request", "check-response-status", "decode-response", ]); export class CloudRelayConfigurationError extends Schema.TaggedErrorClass<CloudRelayConfigurationError>()( "CloudRelayConfigurationError", { configKey: Schema.Literal("T3CODE_RELAY_URL"), cause: Schema.Defect(), }, ) { override get message(): string { return `${this.configKey} must be configured as a secure absolute HTTPS origin.`; } } export class CloudRelayRequestError extends Schema.TaggedErrorClass<CloudRelayRequestError>()( "CloudRelayRequestError", { operation: CloudRelayRequestOperation, phase: CloudRelayRequestPhase, method: Schema.Literal("POST"), url: Schema.String, responseStatus: Schema.optional(Schema.Number), cause: Schema.Defect(), }, ) { static fromClientFailure(input: { readonly operation: CloudRelayRequestError["operation"]; readonly url: string; readonly cause: HttpBody.HttpBodyError | HttpClientError.HttpClientError | Schema.SchemaError; readonly responseStatus?: number; }): CloudRelayRequestError { if (input.cause._tag === "SchemaError") { return new CloudRelayRequestError({ operation: input.operation, phase: "decode-response", method: "POST", url: input.url, ...(input.responseStatus === undefined ? {} : { responseStatus: input.responseStatus }), cause: input.cause, }); } if (!HttpClientError.isHttpClientError(input.cause)) { return new CloudRelayRequestError({ operation: input.operation, phase: "encode-request", method: "POST", url: input.url, cause: input.cause, }); } const phase: CloudRelayRequestError["phase"] = (() => { switch (input.cause.reason._tag) { case "EncodeError": return "encode-request"; case "TransportError": case "InvalidUrlError": return "send-request"; case "StatusCodeError": return "check-response-status"; case "DecodeError": case "EmptyBodyError": return "decode-response"; } })(); return new CloudRelayRequestError({ operation: input.operation, phase, method: "POST", url: input.url, ...(input.cause.response === undefined ? input.responseStatus === undefined ? {} : { responseStatus: input.responseStatus } : { responseStatus: input.cause.response.status }), cause: input.cause, }); } override get message(): string { const responseStatus = this.responseStatus === undefined ? "" : ` with response status ${this.responseStatus}`; return `T3 Connect relay ${this.operation} failed during ${this.phase}${responseStatus}.`; } } const appendCloudCredentialResponseHeaders = HttpEffect.appendPreResponseHandler( (_request, response) => Effect.succeed(HttpServerResponse.setHeaders(response, CLOUD_CREDENTIAL_RESPONSE_HEADERS)), ); const failEnvironmentCloudInternalError = (message: string) => (cause: unknown): Effect.Effect<never, EnvironmentHttpInternalServerError> => Effect.logError(message, { cause }).pipe( Effect.flatMap(() => Effect.fail(new EnvironmentHttpInternalServerError({ message }))), ); const requireRelayUrl = relayUrlConfig.pipe( Effect.mapError( (cause) => new CloudRelayConfigurationError({ configKey: "T3CODE_RELAY_URL", cause, }), ), ); function bytesToString(bytes: Uint8Array): string { return new TextDecoder().decode(bytes); } function stringToBytes(value: string): Uint8Array { return new TextEncoder().encode(value); } export function consumeCloudReplayGuards(input: { readonly secrets: ServerSecretStore.ServerSecretStore["Service"]; readonly names: ReadonlyArray<string>; readonly value: Uint8Array; }) { return Effect.all( input.names.map((name) => input.secrets.create(name, input.value).pipe( Effect.as(true), Effect.catchTags({ SecretStorePersistError: (error) => ServerSecretStore.isSecretAlreadyExistsError(error) ? Effect.succeed(false) : Effect.fail(error), }), ), ), { concurrency: input.names.length }, ).pipe(Effect.map((created) => created.every(Boolean))); } function normalizePemForSignedPayload(value: string): string { return value.trim(); } function normalizeHostname(hostname: string): string { return hostname .trim() .toLowerCase() .replace(/^\[(.*)\]$/, "$1"); } function validateCloudMintPublicKey( publicKey: string, ): Effect.Effect<void, EnvironmentHttpBadRequestError> { return Effect.try({ try: () => NodeCrypto.createPublicKey(publicKey.replace(/\\n/g, "\n")), catch: () => new EnvironmentHttpBadRequestError({ message: "Cloud mint public key must be a valid Ed25519 public key.", }), }).pipe( Effect.flatMap((key) => key.asymmetricKeyType === "ed25519" ? Effect.void : Effect.fail( new EnvironmentHttpBadRequestError({ message: "Cloud mint public key must be a valid Ed25519 public key.", }), ), ), ); } function validateRelayConfigPayload( payload: RelayEnvironmentConfigRequest, ): Effect.Effect<void, EnvironmentHttpBadRequestError> { if (!isSecureRelayUrl(payload.relayUrl)) { return Effect.fail( new EnvironmentHttpBadRequestError({ message: "Relay URL must be a secure absolute HTTPS URL.", }), ); } if (payload.relayIssuer !== undefined && !isSecureRelayUrl(payload.relayIssuer)) { return Effect.fail( new EnvironmentHttpBadRequestError({ message: "Relay issuer must be a secure absolute HTTPS URL.", }), ); } if (payload.environmentCredential.trim().length === 0) { return Effect.fail( new EnvironmentHttpBadRequestError({ message: "Relay environment credential is required.", }), ); } if (payload.cloudUserId.trim().length === 0) { return Effect.fail( new EnvironmentHttpBadRequestError({ message: "Cloud user id is required.", }), ); } return Effect.void; } function validateLinkedCloudUser(input: { readonly secrets: ServerSecretStore.ServerSecretStore["Service"]; readonly cloudUserId: string; }) { return input.secrets.get(CLOUD_LINKED_USER_ID).pipe( Effect.mapError( (cause) => new EnvironmentAuth.ServerAuthLinkedCloudAccountVerificationError({ cause, }), ), Effect.flatMap((existing) => { if (Option.isNone(existing)) { return Effect.void; } const existingCloudUserId = bytesToString(existing.value); return existingCloudUserId === input.cloudUserId ? Effect.void : Effect.fail( new EnvironmentHttpConflictError({ message: "This environment is already linked to a different cloud account. Unlink it before switching accounts.", }), ); }), ); } function readInstalledCloudUserId(secrets: ServerSecretStore.ServerSecretStore["Service"]) { return secrets.get(CLOUD_LINKED_USER_ID).pipe( Effect.mapError( (cause) => new EnvironmentAuth.ServerAuthLinkedCloudAccountReadError({ cause, }), ), Effect.flatMap((bytes) => Option.isSome(bytes) ? Effect.succeed(bytesToString(bytes.value)) : Effect.fail(new EnvironmentAuth.ServerAuthLinkedCloudAccountMissingError({})), ), ); } function isLoopbackHostname(hostname: string): boolean { return LOOPBACK_HOSTNAMES.has(normalizeHostname(hostname)); } function firstForwardedHeaderValue(value: string | undefined): string | undefined { const first = value?.split(",")[0]?.trim(); return first && first.length > 0 ? first : undefined; } function requestAbsoluteUrl(request: HttpServerRequest.HttpServerRequest): string | null { try { return new URL(request.originalUrl).href; } catch { const host = firstForwardedHeaderValue(request.headers.host) ?? "127.0.0.1"; try { return new URL(request.originalUrl, `http://${host}`).href; } catch { return null; } } } function hasForwardedAuthorityHeaders(request: HttpServerRequest.HttpServerRequest): boolean { return ( firstForwardedHeaderValue(request.headers["x-forwarded-host"]) !== undefined || firstForwardedHeaderValue(request.headers["x-forwarded-proto"]) !== undefined ); } function endpointRequestPort(url: URL): number { return Number(url.port || (url.protocol === "https:" ? 443 : 80)); } function isAllowedEndpointOrigin(input: { readonly origin: RelayManagedEndpointOrigin; readonly requestUrl: string; }): boolean { if (!isLoopbackHostname(input.origin.localHttpHost)) { return false; } const url = new URL(input.requestUrl); if (!isLoopbackHostname(url.hostname)) { return false; } return input.origin.localHttpPort === endpointRequestPort(url); } function providerKindMatchesRequestedLinkScopes(request: RelayLinkProofRequest): boolean { return request.endpoint.providerKind === "cloudflare_tunnel"; } function hasExactScope(input: { readonly scopes: ReadonlyArray<string>; readonly expected: string; }): boolean { return input.scopes.length === 1 && input.scopes[0] === input.expected; } function hasBoundedCloudProofLifetime(input: { readonly iat: number; readonly exp: number; readonly nowSeconds: number; }): boolean { return ( input.exp > input.iat && input.exp - input.iat <= CLOUD_PROOF_MAX_LIFETIME_SECONDS && input.iat <= input.nowSeconds + CLOUD_PROOF_CLOCK_SKEW_SECONDS ); } const decodeCloudHealthProof = Schema.decodeUnknownEffect(RelayCloudEnvironmentHealthProofPayload); const decodeCloudMintProof = Schema.decodeUnknownEffect(RelayCloudMintCredentialProofPayload); interface CloudHttpDependencies { readonly secrets: ServerSecretStore.ServerSecretStore["Service"]; readonly environment: ServerEnvironment.ServerEnvironment["Service"]; readonly endpointRuntime: ManagedEndpointRuntime.CloudManagedEndpointRuntime["Service"]; readonly environmentAuth: EnvironmentAuth.EnvironmentAuth["Service"]; readonly cliTokenManager: CliTokenManager.CloudCliTokenManager["Service"]; readonly httpClient: HttpClient.HttpClient; } const cloudHttpDependencies = Effect.gen(function* () { return { secrets: yield* ServerSecretStore.ServerSecretStore, environment: yield* ServerEnvironment.ServerEnvironment, endpointRuntime: yield* ManagedEndpointRuntime.CloudManagedEndpointRuntime, environmentAuth: yield* EnvironmentAuth.EnvironmentAuth, cliTokenManager: yield* CliTokenManager.CloudCliTokenManager, httpClient: yield* HttpClient.HttpClient, } satisfies CloudHttpDependencies; }); const makeCloudLinkProof = Effect.fn("environment.cloud.makeLinkProof")(function* ( dependencies: CloudHttpDependencies, request: RelayLinkProofRequest, requestUrl: string, ) { const keyPair = yield* getOrCreateEnvironmentKeyPairFromSecretStore(dependencies.secrets); if ( !providerKindMatchesRequestedLinkScopes(request) || !isAllowedEndpointOrigin({ origin: request.origin, requestUrl, }) ) { return yield* new EnvironmentHttpBadRequestError({ message: "Invalid managed endpoint origin.", }); } const now = yield* DateTime.now; const expiresAt = DateTime.add(now, { minutes: 5 }); const nowSeconds = Math.floor(now.epochMilliseconds / 1_000); const descriptor = yield* dependencies.environment.getDescriptor; const payload = { iss: `t3-env:${descriptor.environmentId}`, aud: normalizeRelayIssuer(request.relayIssuer), sub: descriptor.environmentId, jti: yield* Crypto.Crypto.pipe(Effect.flatMap((crypto) => crypto.randomUUIDv4)), iat: nowSeconds, exp: Math.floor(expiresAt.epochMilliseconds / 1_000), challenge: request.challenge, descriptor, environmentId: descriptor.environmentId, environmentPublicKey: normalizePemForSignedPayload(keyPair.publicKey), endpoint: request.endpoint, origin: request.origin, scopes: ["agent_activity_notifications", "managed_tunnels"], } satisfies RelayEnvironmentLinkProofPayload; return yield* signRelayJwt({ privateKey: keyPair.privateKey, typ: RELAY_LINK_PROOF_TYP, payload, }).pipe( Effect.mapError( (cause) => new EnvironmentAuth.ServerAuthCloudLinkJwtSigningError({ cause, }), ), ); }); const cloudLinkProofHandler = Effect.fn("environment.cloud.linkProof")( function* (dependencies: CloudHttpDependencies, request: RelayLinkProofRequest) { yield* requireEnvironmentScope(AuthRelayWriteScope);