Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/egress-proxy-tls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"e2b": minor
"@e2b/python-sdk": minor
---

Add `tls` to the egress proxy options as `true` or `{ serverName?, caCert? }` (`server_name`/`ca_cert` in Python); `getInfo`/`get_info` reports it without the CA.
12 changes: 11 additions & 1 deletion packages/js-sdk/src/api/schema.gen.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion packages/js-sdk/src/envd/schema.gen.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/js-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export type {
SandboxIamToken,
SandboxIamTokenType,
SandboxEgressProxyOpts,
SandboxEgressProxyTLSOpts,
SandboxEgressProxyInfo,
SandboxEgressProxyTLSInfo,
SandboxNetworkOpts,
SandboxNetworkInfo,
SandboxNetworkSelector,
Expand Down
85 changes: 83 additions & 2 deletions packages/js-sdk/src/sandbox/sandboxApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export type SandboxNetworkSelector =
* address: 'proxy.example.com:1080',
* username: 'proxy-user',
* password: 'proxy-password',
* tls: true,
* },
* },
* })
Expand Down Expand Up @@ -198,18 +199,59 @@ export type SandboxEgressProxyOpts = {
* {@link SandboxEgressProxyOpts.username}.
*/
password?: string

/**
* Connect to the proxy over TLS. The SOCKS5 handshake, credentials, and
* tunneled traffic run inside the TLS session; TLS protects only the hop to
* the proxy. The certificate is always verified, TLS 1.2 or newer is
* required, and failures never fall back to plaintext.
*
* Set to `true` to use the system trust store and the host part of `address`
* for SNI. Passing an object also enables TLS, with optional custom
* `serverName` and `caCert`.
*/
tls?: boolean | SandboxEgressProxyTLSOpts
}

/**
* TLS settings for the connection to a BYOP SOCKS5 proxy.
*/
export type SandboxEgressProxyTLSOpts = {
/**
* Name to verify the proxy certificate against and send as SNI, up to 253
* characters. Defaults to the host part of `address`; set this only when the
* certificate does not match the address.
*/
serverName?: string

/**
* One or more PEM CA certificates, up to 8192 bytes. This replaces the
* system trust store rather than adding to it.
*/
caCert?: string
}

/**
* Egress proxy as returned by the sandbox info endpoint. Mirrors
* {@link SandboxEgressProxyOpts} without `password` — the API never returns
* it.
* {@link SandboxEgressProxyOpts} without `password` or `caCert` — the API
* never returns them.
*/
export type SandboxEgressProxyInfo = {
/** See {@link SandboxEgressProxyOpts.address}. */
address: string
/** See {@link SandboxEgressProxyOpts.username}. */
username?: string
/** Set when TLS to the proxy is on. */
tls?: SandboxEgressProxyTLSInfo
}

/**
* TLS status for the egress proxy connection. The CA certificate is never
* returned by the API.
*/
export type SandboxEgressProxyTLSInfo = {
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
/** See {@link SandboxEgressProxyTLSOpts.serverName}. */
serverName?: string
}

export type SandboxNetworkOpts = {
Expand Down Expand Up @@ -377,6 +419,9 @@ export type SandboxNetworkUpdate = {
* traffic out directly — even when the update was only meant to change the
* allow and deny lists. Repeat it in every update that should keep
* tunneling.
*
* The same replace semantics apply to `tls`: an update that repeats
* `address` but omits `tls` keeps tunneling without TLS.
*/
egressProxy?: SandboxEgressProxyOpts
/**
Expand Down Expand Up @@ -1157,13 +1202,40 @@ function buildEgressProxyBody(
)
}

const tls = egressProxy.tls
if (tls != null && typeof tls !== 'boolean' && !isPlainObject(tls)) {
throw new InvalidArgumentError(
'network egressProxy tls must be a boolean or an object.'
)
}
if (
isPlainObject(tls) &&
Object.prototype.hasOwnProperty.call(tls, 'enabled')
) {
throw new InvalidArgumentError(
"network egressProxy tls takes no 'enabled'; pass tls: true or tls: false instead."
)
}

const tlsBody =
tls === true
? { enabled: true }
: tls != null && typeof tls === 'object'
? {
enabled: true,
...(tls.serverName != null ? { serverName: tls.serverName } : {}),
...(tls.caCert != null ? { caCert: tls.caCert } : {}),
}
: undefined

// `!= null` also skips a `null` credential, which is what reading one out of
// an unset environment variable yields and what "this proxy takes no
// credentials" means; the API only accepts a string.
return {
address: egressProxy.address,
...(egressProxy.username != null ? { username: egressProxy.username } : {}),
...(egressProxy.password != null ? { password: egressProxy.password } : {}),
...(tlsBody !== undefined ? { tls: tlsBody } : {}),
}
}

Expand Down Expand Up @@ -1222,6 +1294,15 @@ function fromApiEgressProxy(
...(egressProxy.username !== undefined
? { username: egressProxy.username }
: {}),
...(egressProxy.tls?.enabled === true
? {
tls: {
...(egressProxy.tls.serverName !== undefined
? { serverName: egressProxy.tls.serverName }
: {}),
},
}
: {}),
}
}

Expand Down
Loading
Loading