mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: allow bypassing current CORS magic based on template config (#18706)
Solves https://github.com/coder/coder/issues/15096 This is a slight rework/refactor of the earlier PRs from @dannykopping and @Emyrk: - https://github.com/coder/coder/pull/15669 - https://github.com/coder/coder/pull/15684 - https://github.com/coder/coder/pull/17596 Rather than having a per-app CORS behaviour setting and additionally a template level setting for ports, this PR adds a single template level CORS behaviour setting that is then used by all apps/ports for workspaces created from that template. The main changes are in `proxy.go` and `request.go` to: a) get the CORS behaviour setting from the template b) have `HandleSubdomain` bypass the CORS middleware handler if the selected behaviour is `passthru` c) in `proxyWorkspaceApp`, do not modify the response if the selected behaviour is `passthru` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for configuring CORS behavior ("simple" or "passthru") at the template level for all shared ports. * Introduced a new "CORS Behavior" setting in the template creation and settings forms. * API endpoints and responses now include the optional `cors_behavior` property for templates. * Workspace apps and proxy now honor the specified CORS behavior, enabling conditional CORS middleware application. * Enhanced workspace app tests with comprehensive scenarios covering CORS behaviors and authentication states. * **Bug Fixes** * None. * **Documentation** * Updated API and admin documentation to describe the new `cors_behavior` property and its usage. * Added examples and schema references for CORS behavior in relevant API docs. * **Tests** * Extended automated tests to cover different CORS behavior scenarios for templates and workspace apps. * **Chores** * Updated audit logging to track changes to the `cors_behavior` field on templates. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Callum Styan <callumstyan@gmail.com>
This commit is contained in:
@@ -30,6 +30,7 @@ test("update template schedule settings without override other settings", async
|
||||
disable_everyone_group_access: false,
|
||||
require_active_version: true,
|
||||
max_port_share_level: null,
|
||||
cors_behavior: null,
|
||||
allow_user_cancel_workspace_jobs: null,
|
||||
});
|
||||
|
||||
|
||||
Generated
+8
@@ -307,6 +307,11 @@ export const BypassRatelimitHeader = "X-Coder-Bypass-Ratelimit";
|
||||
// From codersdk/client.go
|
||||
export const CLITelemetryHeader = "Coder-CLI-Telemetry";
|
||||
|
||||
// From codersdk/cors_behavior.go
|
||||
export type CORSBehavior = "passthru" | "simple";
|
||||
|
||||
export const CORSBehaviors: CORSBehavior[] = ["passthru", "simple"];
|
||||
|
||||
// From codersdk/workspacebuilds.go
|
||||
export interface CancelWorkspaceBuildParams {
|
||||
readonly expect_status?: CancelWorkspaceBuildStatus;
|
||||
@@ -492,6 +497,7 @@ export interface CreateTemplateRequest {
|
||||
readonly require_active_version: boolean;
|
||||
readonly max_port_share_level: WorkspaceAgentPortShareLevel | null;
|
||||
readonly template_use_classic_parameter_flow?: boolean;
|
||||
readonly cors_behavior: CORSBehavior | null;
|
||||
}
|
||||
|
||||
// From codersdk/templateversions.go
|
||||
@@ -2816,6 +2822,7 @@ export interface Template {
|
||||
readonly time_til_dormant_autodelete_ms: number;
|
||||
readonly require_active_version: boolean;
|
||||
readonly max_port_share_level: WorkspaceAgentPortShareLevel;
|
||||
readonly cors_behavior: CORSBehavior;
|
||||
readonly use_classic_parameter_flow: boolean;
|
||||
}
|
||||
|
||||
@@ -3188,6 +3195,7 @@ export interface UpdateTemplateMeta {
|
||||
readonly deprecation_message?: string;
|
||||
readonly disable_everyone_group_access: boolean;
|
||||
readonly max_port_share_level?: WorkspaceAgentPortShareLevel;
|
||||
readonly cors_behavior?: CORSBehavior;
|
||||
readonly use_classic_parameter_flow?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ export const newTemplate = (
|
||||
const safeTemplateData = {
|
||||
name: formData.name,
|
||||
max_port_share_level: null,
|
||||
cors_behavior: null,
|
||||
display_name: formData.display_name,
|
||||
description: formData.description,
|
||||
icon: formData.icon,
|
||||
|
||||
+25
@@ -4,6 +4,7 @@ import FormHelperText from "@mui/material/FormHelperText";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import {
|
||||
CORSBehaviors,
|
||||
type Template,
|
||||
type UpdateTemplateMeta,
|
||||
WorkspaceAppSharingLevels,
|
||||
@@ -52,6 +53,7 @@ export const validationSchema = Yup.object({
|
||||
use_classic_parameter_flow: Yup.boolean(),
|
||||
deprecation_message: Yup.string(),
|
||||
max_port_sharing_level: Yup.string().oneOf(WorkspaceAppSharingLevels),
|
||||
cors_behavior: Yup.string().oneOf(Object.values(CORSBehaviors)),
|
||||
});
|
||||
|
||||
export interface TemplateSettingsForm {
|
||||
@@ -93,6 +95,7 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
|
||||
disable_everyone_group_access: false,
|
||||
max_port_share_level: template.max_port_share_level,
|
||||
use_classic_parameter_flow: template.use_classic_parameter_flow,
|
||||
cors_behavior: template.cors_behavior,
|
||||
},
|
||||
validationSchema,
|
||||
onSubmit,
|
||||
@@ -338,6 +341,28 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
|
||||
</FormFields>
|
||||
</FormSection>
|
||||
|
||||
<FormSection
|
||||
title="CORS Behavior"
|
||||
description="Control how Cross-Origin Resource Sharing (CORS) requests are handled for all shared ports."
|
||||
>
|
||||
<FormFields>
|
||||
<TextField
|
||||
{...getFieldHelpers("cors_behavior", {
|
||||
helperText:
|
||||
"Use Passthru to bypass Coder's built-in CORS protection.",
|
||||
})}
|
||||
disabled={isSubmitting}
|
||||
fullWidth
|
||||
select
|
||||
value={form.values.cors_behavior}
|
||||
label="CORS Behavior"
|
||||
>
|
||||
<MenuItem value="simple">Simple (recommended)</MenuItem>
|
||||
<MenuItem value="passthru">Passthru</MenuItem>
|
||||
</TextField>
|
||||
</FormFields>
|
||||
</FormSection>
|
||||
|
||||
<FormFooter>
|
||||
<Button onClick={onCancel} variant="outline">
|
||||
Cancel
|
||||
|
||||
+1
@@ -55,6 +55,7 @@ const validFormValues: FormValues = {
|
||||
disable_everyone_group_access: false,
|
||||
max_port_share_level: "owner",
|
||||
use_classic_parameter_flow: true,
|
||||
cors_behavior: "simple",
|
||||
};
|
||||
|
||||
const renderTemplateSettingsPage = async () => {
|
||||
|
||||
@@ -827,6 +827,7 @@ export const MockTemplate: TypesGen.Template = {
|
||||
deprecation_message: "",
|
||||
max_port_share_level: "public",
|
||||
use_classic_parameter_flow: false,
|
||||
cors_behavior: "simple",
|
||||
};
|
||||
|
||||
const MockTemplateVersionFiles: TemplateVersionFiles = {
|
||||
|
||||
Reference in New Issue
Block a user