Compare commits

...

3 Commits

Author SHA1 Message Date
Asher
e37b35278d Account for disabled proxy in startup logs 2023-07-27 09:26:11 -08:00
Asher
2ffbcfdfcb Release v4.15.0 2023-07-21 15:30:03 -08:00
Ryan Brainard
74da5167a2 Add --disable-proxy option (#6349) 2023-07-21 15:23:21 -08:00
11 changed files with 115 additions and 6 deletions

View File

@@ -22,6 +22,25 @@ Code v99.99.999
## Unreleased
### Added
- `--disable-proxy` flag. This disables the domain and path proxies but it does
not disable the ports panel in Code. That can be disabled by using
`remote.autoForwardPorts=false` in your settings.
## [4.15.0](https://github.com/coder/code-server/releases/tag/v4.15.0) - 2023-07-21
Code v1.80.1
### Changed
- Updated to Code 1.80.1.
### Added
- `--trusted-origin` flag for specifying origins that you trust but do not
control (for example a reverse proxy).
Code v1.79.2
## [4.14.1](https://github.com/coder/code-server/releases/tag/v4.14.1) - 2023-06-26

View File

@@ -15,9 +15,9 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 3.10.1
version: 3.11.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.14.1
appVersion: 4.15.0

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.14.1'
tag: '4.15.0'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a

View File

@@ -34,6 +34,7 @@
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
- [How do I change the port?](#how-do-i-change-the-port)
- [How do I hide the coder/coder promotion in Help: Getting Started?](#how-do-i-hide-the-codercoder-promotion-in-help-getting-started)
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
- [How do I disable file download?](#how-do-i-disable-file-download)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -453,6 +454,19 @@ You can pass the flag `--disable-getting-started-override` to `code-server` or
you can set the environment variable `CS_DISABLE_GETTING_STARTED_OVERRIDE=1` or
`CS_DISABLE_GETTING_STARTED_OVERRIDE=true`.
## How do I disable the proxy?
You can pass the flag `--disable-proxy` to `code-server` or
you can set the environment variable `CS_DISABLE_PROXY=1` or
`CS_DISABLE_PROXY=true`.
Note, this option currently only disables the proxy routes to forwarded ports, including
the domain and path proxy routes over HTTP and WebSocket; however, it does not
disable the automatic port forwarding in the VS Code workbench itself. In other words,
user will still see the Ports tab and notifications, but will not be able to actually
use access the ports. It is recommended to set `remote.autoForwardPorts` to `false`
when using the option.
## How do I disable file download?
You can pass the flag `--disable-file-downloads` to `code-server`

View File

@@ -51,6 +51,7 @@ export interface UserProvidedCodeArgs {
"disable-file-downloads"?: boolean
"disable-workspace-trust"?: boolean
"disable-getting-started-override"?: boolean
"disable-proxy"?: boolean
"session-socket"?: string
}
@@ -178,6 +179,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
type: "boolean",
description: "Disable the coder/coder override in the Help: Getting Started page.",
},
"disable-proxy": {
type: "boolean",
description: "Disable domain and path proxy routes.",
},
// --enable can be used to enable experimental features. These features
// provide no guarantees.
enable: { type: "string[]" },
@@ -564,6 +569,10 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args["disable-getting-started-override"] = true
}
if (process.env.CS_DISABLE_PROXY?.match(/^(1|true)$/)) {
args["disable-proxy"] = true
}
const usingEnvHashedPassword = !!process.env.HASHED_PASSWORD
if (process.env.HASHED_PASSWORD) {
args["hashed-password"] = process.env.HASHED_PASSWORD

View File

@@ -75,6 +75,25 @@ export const replaceTemplates = <T extends object>(
.replace("{{OPTIONS}}", () => escapeJSON(serverOptions))
}
/**
* Throw an error if proxy is not enabled. Call `next` if provided.
*/
export const ensureProxyEnabled = (req: express.Request, _?: express.Response, next?: express.NextFunction): void => {
if (!proxyEnabled(req)) {
throw new HttpError("Forbidden", HttpCode.Forbidden)
}
if (next) {
next()
}
}
/**
* Return true if proxy is enabled.
*/
export const proxyEnabled = (req: express.Request): boolean => {
return !req.args["disable-proxy"]
}
/**
* Throw an error if not authorized. Call `next` if provided.
*/

View File

@@ -144,7 +144,9 @@ export const runCodeServer = async (
logger.info(" - Not serving HTTPS")
}
if (args["proxy-domain"].length > 0) {
if (args["disable-proxy"]) {
logger.info(" - Proxy disabled")
} else if (args["proxy-domain"].length > 0) {
logger.info(` - ${plural(args["proxy-domain"].length, "Proxying the following domain")}:`)
args["proxy-domain"].forEach((domain) => logger.info(` - ${domain}`))
}

View File

@@ -1,6 +1,6 @@
import { Request, Router } from "express"
import { HttpCode, HttpError } from "../../common/http"
import { getHost, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
import { getHost, ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
import { proxy } from "../proxy"
import { Router as WsRouter } from "../wsRouter"
@@ -59,6 +59,8 @@ router.all("*", async (req, res, next) => {
return next()
}
ensureProxyEnabled(req)
// Must be authenticated to use the proxy.
const isAuthenticated = await authenticated(req)
if (!isAuthenticated) {
@@ -100,6 +102,8 @@ wsRouter.ws("*", async (req, _, next) => {
if (!port) {
return next()
}
ensureProxyEnabled(req)
ensureOrigin(req)
await ensureAuthenticated(req)
proxy.ws(req, req.ws, req.head, {

View File

@@ -3,7 +3,7 @@ import * as path from "path"
import * as qs from "qs"
import * as pluginapi from "../../../typings/pluginapi"
import { HttpCode, HttpError } from "../../common/http"
import { authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
import { ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
import { proxy as _proxy } from "../proxy"
const getProxyTarget = (req: Request, passthroughPath?: boolean): string => {
@@ -21,6 +21,8 @@ export async function proxy(
passthroughPath?: boolean
},
): Promise<void> {
ensureProxyEnabled(req)
if (!(await authenticated(req))) {
// If visiting the root (/:port only) redirect to the login page.
if (!req.params[0] || req.params[0] === "/") {
@@ -50,6 +52,7 @@ export async function wsProxy(
passthroughPath?: boolean
},
): Promise<void> {
ensureProxyEnabled(req)
ensureOrigin(req)
await ensureAuthenticated(req)
_proxy.ws(req, req.ws, req.head, {

View File

@@ -47,6 +47,7 @@ describe("parser", () => {
delete process.env.CS_DISABLE_FILE_DOWNLOADS
delete process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE
delete process.env.VSCODE_PROXY_URI
delete process.env.CS_DISABLE_PROXY
console.log = jest.fn()
})
@@ -103,6 +104,8 @@ describe("parser", () => {
"--disable-getting-started-override",
"--disable-proxy",
["--session-socket", "/tmp/override-code-server-ipc-socket"],
["--host", "0.0.0.0"],
@@ -123,6 +126,7 @@ describe("parser", () => {
},
"disable-file-downloads": true,
"disable-getting-started-override": true,
"disable-proxy": true,
enable: ["feature1", "feature2"],
help: true,
host: "0.0.0.0",
@@ -392,6 +396,30 @@ describe("parser", () => {
})
})
it("should use env var CS_DISABLE_PROXY", async () => {
process.env.CS_DISABLE_PROXY = "1"
const args = parse([])
expect(args).toEqual({})
const defaultArgs = await setDefaults(args)
expect(defaultArgs).toEqual({
...defaults,
"disable-proxy": true,
})
})
it("should use env var CS_DISABLE_PROXY set to true", async () => {
process.env.CS_DISABLE_PROXY = "true"
const args = parse([])
expect(args).toEqual({})
const defaultArgs = await setDefaults(args)
expect(defaultArgs).toEqual({
...defaults,
"disable-proxy": true,
})
})
it("should error if password passed in", () => {
expect(() => parse(["--password", "supersecret123"])).toThrowError(
"--password can only be set in the config file or passed in via $PASSWORD",

View File

@@ -45,6 +45,17 @@ describe("proxy", () => {
jest.clearAllMocks()
})
it("should return 403 Forbidden if proxy is disabled", async () => {
e.get("/wsup", (req, res) => {
res.json("you cannot see this")
})
codeServer = await integration.setup(["--auth=none", "--disable-proxy"], "")
const resp = await codeServer.fetch(proxyPath)
expect(resp.status).toBe(403)
const json = await resp.json()
expect(json).toEqual({ error: "Forbidden" })
})
it("should rewrite the base path", async () => {
e.get("/wsup", (req, res) => {
res.json("asher is the best")