mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00: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:
@@ -559,6 +559,64 @@ func AllConnectionTypeValues() []ConnectionType {
|
||||
}
|
||||
}
|
||||
|
||||
type CorsBehavior string
|
||||
|
||||
const (
|
||||
CorsBehaviorSimple CorsBehavior = "simple"
|
||||
CorsBehaviorPassthru CorsBehavior = "passthru"
|
||||
)
|
||||
|
||||
func (e *CorsBehavior) Scan(src interface{}) error {
|
||||
switch s := src.(type) {
|
||||
case []byte:
|
||||
*e = CorsBehavior(s)
|
||||
case string:
|
||||
*e = CorsBehavior(s)
|
||||
default:
|
||||
return fmt.Errorf("unsupported scan type for CorsBehavior: %T", src)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type NullCorsBehavior struct {
|
||||
CorsBehavior CorsBehavior `json:"cors_behavior"`
|
||||
Valid bool `json:"valid"` // Valid is true if CorsBehavior is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (ns *NullCorsBehavior) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
ns.CorsBehavior, ns.Valid = "", false
|
||||
return nil
|
||||
}
|
||||
ns.Valid = true
|
||||
return ns.CorsBehavior.Scan(value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (ns NullCorsBehavior) Value() (driver.Value, error) {
|
||||
if !ns.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return string(ns.CorsBehavior), nil
|
||||
}
|
||||
|
||||
func (e CorsBehavior) Valid() bool {
|
||||
switch e {
|
||||
case CorsBehaviorSimple,
|
||||
CorsBehaviorPassthru:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func AllCorsBehaviorValues() []CorsBehavior {
|
||||
return []CorsBehavior{
|
||||
CorsBehaviorSimple,
|
||||
CorsBehaviorPassthru,
|
||||
}
|
||||
}
|
||||
|
||||
type CryptoKeyFeature string
|
||||
|
||||
const (
|
||||
@@ -3474,6 +3532,7 @@ type Template struct {
|
||||
ActivityBump int64 `db:"activity_bump" json:"activity_bump"`
|
||||
MaxPortSharingLevel AppSharingLevel `db:"max_port_sharing_level" json:"max_port_sharing_level"`
|
||||
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
|
||||
CorsBehavior CorsBehavior `db:"cors_behavior" json:"cors_behavior"`
|
||||
CreatedByAvatarURL string `db:"created_by_avatar_url" json:"created_by_avatar_url"`
|
||||
CreatedByUsername string `db:"created_by_username" json:"created_by_username"`
|
||||
CreatedByName string `db:"created_by_name" json:"created_by_name"`
|
||||
@@ -3521,7 +3580,8 @@ type TemplateTable struct {
|
||||
ActivityBump int64 `db:"activity_bump" json:"activity_bump"`
|
||||
MaxPortSharingLevel AppSharingLevel `db:"max_port_sharing_level" json:"max_port_sharing_level"`
|
||||
// Determines whether to default to the dynamic parameter creation flow for this template or continue using the legacy classic parameter creation flow.This is a template wide setting, the template admin can revert to the classic flow if there are any issues. An escape hatch is required, as workspace creation is a core workflow and cannot break. This column will be removed when the dynamic parameter creation flow is stable.
|
||||
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
|
||||
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
|
||||
CorsBehavior CorsBehavior `db:"cors_behavior" json:"cors_behavior"`
|
||||
}
|
||||
|
||||
// Records aggregated usage statistics for templates/users. All usage is rounded up to the nearest minute.
|
||||
|
||||
Reference in New Issue
Block a user