diff --git a/docs/config.md b/docs/config.md index bf0a82c2..c884f6e8 100644 --- a/docs/config.md +++ b/docs/config.md @@ -12,6 +12,8 @@ nointernet: true/false risectldir: string ee: code: string +auth: + disable: true/false server: init: string host: string @@ -47,6 +49,7 @@ You can override the YAML configuration settings by using environment variables. | `RCONSOLE_NOINTERNET` | `true/false` | (Optional) Whether to disable internet access, default is false. If public internet is not allowed, set it to true. Then mount risectl files to //risectl. | | `RCONSOLE_RISECTLDIR` | `string` | (Optional) The path of the directory to store the risectl files, default is "$HOME/.risectl" | | `RCONSOLE_EE_CODE` | `string` | (Optional) The activation code of the enterprise edition, if not set, the enterprise edition will be disabled. | +| `RCONSOLE_AUTH_DISABLE` | `true/false` | (Optional) Whether to disable authentication, default is false. When disabled, all API endpoints will be accessible without authentication. Useful when using an external authentication proxy (e.g., OAuth2 proxy). WARNING: Only use in trusted environments or behind a secure proxy. | | `RCONSOLE_SERVER_INIT` | `string` | (Optional) The path of file to store the initialization data, if not set, skip the initialization | | `RCONSOLE_SERVER_HOST` | `string` | (Optional) The host of the anclax server. | | `RCONSOLE_SERVER_PORT` | `integer` | (Optional) The port of the anclax server, default is 8020 | diff --git a/pkg/config/config.go b/pkg/config/config.go index 4cf1cc1c..7fd28f3f 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -12,6 +12,14 @@ type Root struct { Password string `yaml:"password"` } +type AuthConfig struct { + // (Optional) Whether to disable authentication, default is false. + // When disabled, all API endpoints will be accessible without authentication. + // This is useful when using an external authentication proxy (e.g., OAuth2 proxy). + // WARNING: Only use this in trusted environments or behind a secure proxy. + Disable bool `yaml:"disable,omitempty"` +} + type Config struct { // (Optional) The path of file to store the initialization data, if not set, skip the initialization Init string `yaml:"init,omitempty"` @@ -30,6 +38,9 @@ type Config struct { Server anclax_config.Config `yaml:"server,omitempty"` + // Authentication configuration + Auth AuthConfig `yaml:"auth,omitempty"` + // (Optional) The alias of the server endpoint, it is used in the API endpoint of the web UI. // It should start with http:// or https:// and end with /api/v1 in normal case. e.g. https://mydomain.app/api/v1 // If not set, the endpoint will be http://host:port. You can also add path to the alias, e.g. http://endpointalias/my/root/path. diff --git a/pkg/controller/validator.go b/pkg/controller/validator.go index bae4d180..46390b09 100644 --- a/pkg/controller/validator.go +++ b/pkg/controller/validator.go @@ -5,21 +5,33 @@ import ( "github.com/cloudcarver/anclax/pkg/auth" "github.com/gofiber/fiber/v2" + "github.com/risingwavelabs/risingwave-console/pkg/config" "github.com/risingwavelabs/risingwave-console/pkg/zcore/model" "github.com/risingwavelabs/risingwave-console/pkg/zgen/apigen" "github.com/risingwavelabs/risingwave-console/pkg/zgen/querier" ) +// DefaultOrgID is used when authentication is disabled +const DefaultOrgID int32 = 1 + type Validator struct { - model model.ModelInterface - auth auth.AuthInterface + model model.ModelInterface + auth auth.AuthInterface + authDisable bool } -func NewValidator(model model.ModelInterface, auth auth.AuthInterface) apigen.Validator { - return &Validator{model: model, auth: auth} +func NewValidator(model model.ModelInterface, auth auth.AuthInterface, cfg *config.Config) apigen.Validator { + return &Validator{ + model: model, + auth: auth, + authDisable: cfg.Auth.Disable, + } } func (v *Validator) GetOrgID(c *fiber.Ctx) int32 { + if v.authDisable { + return DefaultOrgID + } return c.Locals(auth.ContextKeyOrgID).(int32) } @@ -35,6 +47,12 @@ func (v *Validator) OwnDatabase(c *fiber.Ctx, orgID int32, databaseID int32) err } func (v *Validator) AuthFunc(c *fiber.Ctx) error { + if v.authDisable { + // When auth is disabled, set the default OrgID in context + // so that downstream handlers can still access it + c.Locals(auth.ContextKeyOrgID, DefaultOrgID) + return nil + } return v.auth.Authfunc(c) } diff --git a/wire/wire_gen.go b/wire/wire_gen.go index 8bc0c1ac..5d67115f 100644 --- a/wire/wire_gen.go +++ b/wire/wire_gen.go @@ -62,7 +62,7 @@ func InitializeApplication() (*app.App, error) { } globalContext := injection.InjectGlobalctx(application) serverInterface := controller.NewSeverInterface(serviceServiceInterface, authInterface, globalContext) - validator := controller.NewValidator(modelInterface, authInterface) + validator := controller.NewValidator(modelInterface, authInterface, configConfig) executorInterface := task.NewTaskExecutor(taskRunner, modelInterface, risectlManagerInterface, metaHttpManagerInterface) taskHandler := taskgen.NewTaskHandler(executorInterface) plugin := app.NewPlugin(serverInterface, validator, taskHandler) @@ -99,7 +99,7 @@ func InitializePlugin(cfg *config.Config, anclaxApp *app2.Application) (app2.Plu } globalContext := injection.InjectGlobalctx(anclaxApp) serverInterface := controller.NewSeverInterface(serviceServiceInterface, authInterface, globalContext) - validator := controller.NewValidator(modelInterface, authInterface) + validator := controller.NewValidator(modelInterface, authInterface, cfg) executorInterface := task.NewTaskExecutor(taskRunner, modelInterface, risectlManagerInterface, metaHttpManagerInterface) taskHandler := taskgen.NewTaskHandler(executorInterface) plugin := app.NewPlugin(serverInterface, validator, taskHandler)