mirror of https://github.com/coder/coder.git
feat: add flag to disable password auth (#5991)
Adds a flag --disable-password-auth that prevents the password login endpoint from working unless the user has the "owner" (aka. site admin) role. Adds a subcommand `coder server create-admin-user` which creates a user directly in the database with the "owner" role, the "admin" role in every organization, and password auth. This is to avoid lock-out situations where all accounts have the login type set to an identity provider and nobody can login.
This commit is contained in:
parent
968d7e4dc5
commit
4fe221a700
|
@ -532,7 +532,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
|
|||
{
|
||||
name: "Start/End out of order",
|
||||
matches: []match{
|
||||
//{match: "Continue?", write: "yes"},
|
||||
// {match: "Continue?", write: "yes"},
|
||||
},
|
||||
writeConfig: writeConfig{
|
||||
ssh: strings.Join([]string{
|
||||
|
@ -547,7 +547,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
|
|||
{
|
||||
name: "Multiple sections",
|
||||
matches: []match{
|
||||
//{match: "Continue?", write: "yes"},
|
||||
// {match: "Continue?", write: "yes"},
|
||||
},
|
||||
writeConfig: writeConfig{
|
||||
ssh: strings.Join([]string{
|
||||
|
|
|
@ -550,6 +550,12 @@ func newConfig() *codersdk.DeploymentConfig {
|
|||
Flag: "disable-session-expiry-refresh",
|
||||
Default: false,
|
||||
},
|
||||
DisablePasswordAuth: &codersdk.DeploymentConfigField[bool]{
|
||||
Name: "Disable Password Authentication",
|
||||
Usage: "Disable password authentication. This is recommended for security purposes in production deployments that rely on an identity provider. Any user with the owner role will be able to sign in with their password regardless of this setting to avoid potential lock out. If you are locked out of your account, you can use the `coder server create-admin` command to create a new admin user directly in the database.",
|
||||
Flag: "disable-password-auth",
|
||||
Default: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
130
cli/server.go
130
cli/server.go
|
@ -563,62 +563,13 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
|
|||
options.Database = dbfake.New()
|
||||
options.Pubsub = database.NewPubsubInMemory()
|
||||
} else {
|
||||
logger.Debug(ctx, "connecting to postgresql")
|
||||
sqlDB, err := sql.Open(sqlDriver, cfg.PostgresURL.Value)
|
||||
sqlDB, err := connectToPostgres(ctx, logger, sqlDriver, cfg.PostgresURL.Value)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("dial postgres: %w", err)
|
||||
return xerrors.Errorf("connect to postgres: %w", err)
|
||||
}
|
||||
defer sqlDB.Close()
|
||||
|
||||
pingCtx, pingCancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
defer pingCancel()
|
||||
|
||||
err = sqlDB.PingContext(pingCtx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("ping postgres: %w", err)
|
||||
}
|
||||
|
||||
// Ensure the PostgreSQL version is >=13.0.0!
|
||||
version, err := sqlDB.QueryContext(ctx, "SHOW server_version;")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get postgres version: %w", err)
|
||||
}
|
||||
if !version.Next() {
|
||||
return xerrors.Errorf("no rows returned for version select")
|
||||
}
|
||||
var versionStr string
|
||||
err = version.Scan(&versionStr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("scan version: %w", err)
|
||||
}
|
||||
_ = version.Close()
|
||||
versionStr = strings.Split(versionStr, " ")[0]
|
||||
if semver.Compare("v"+versionStr, "v13") < 0 {
|
||||
return xerrors.New("PostgreSQL version must be v13.0.0 or higher!")
|
||||
}
|
||||
logger.Debug(ctx, "connected to postgresql", slog.F("version", versionStr))
|
||||
|
||||
err = migrations.Up(sqlDB)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("migrate up: %w", err)
|
||||
}
|
||||
// The default is 0 but the request will fail with a 500 if the DB
|
||||
// cannot accept new connections, so we try to limit that here.
|
||||
// Requests will wait for a new connection instead of a hard error
|
||||
// if a limit is set.
|
||||
sqlDB.SetMaxOpenConns(10)
|
||||
// Allow a max of 3 idle connections at a time. Lower values end up
|
||||
// creating a lot of connection churn. Since each connection uses about
|
||||
// 10MB of memory, we're allocating 30MB to Postgres connections per
|
||||
// replica, but is better than causing Postgres to spawn a thread 15-20
|
||||
// times/sec. PGBouncer's transaction pooling is not the greatest so
|
||||
// it's not optimal for us to deploy.
|
||||
//
|
||||
// This was set to 10 before we started doing HA deployments, but 3 was
|
||||
// later determined to be a better middle ground as to not use up all
|
||||
// of PGs default connection limit while simultaneously avoiding a lot
|
||||
// of connection churn.
|
||||
sqlDB.SetMaxIdleConns(3)
|
||||
defer func() {
|
||||
_ = sqlDB.Close()
|
||||
}()
|
||||
|
||||
options.Database = database.New(sqlDB)
|
||||
options.Pubsub, err = database.NewPubsub(ctx, sqlDB, cfg.PostgresURL.Value)
|
||||
|
@ -1007,7 +958,8 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
|
|||
postgresBuiltinURLCmd.Flags().BoolVar(&pgRawURL, "raw-url", false, "Output the raw connection URL instead of a psql command.")
|
||||
postgresBuiltinServeCmd.Flags().BoolVar(&pgRawURL, "raw-url", false, "Output the raw connection URL instead of a psql command.")
|
||||
|
||||
root.AddCommand(postgresBuiltinURLCmd, postgresBuiltinServeCmd)
|
||||
createAdminUserCommand := newCreateAdminUserCommand()
|
||||
root.AddCommand(postgresBuiltinURLCmd, postgresBuiltinServeCmd, createAdminUserCommand)
|
||||
|
||||
deployment.AttachFlags(root.Flags(), vip, false)
|
||||
|
||||
|
@ -1607,3 +1559,71 @@ func buildLogger(cmd *cobra.Command, cfg *codersdk.DeploymentConfig) (slog.Logge
|
|||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func connectToPostgres(ctx context.Context, logger slog.Logger, driver string, dbURL string) (*sql.DB, error) {
|
||||
logger.Debug(ctx, "connecting to postgresql")
|
||||
sqlDB, err := sql.Open(driver, dbURL)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("dial postgres: %w", err)
|
||||
}
|
||||
|
||||
ok := false
|
||||
defer func() {
|
||||
if !ok {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
pingCtx, pingCancel := context.WithTimeout(ctx, 15*time.Second)
|
||||
defer pingCancel()
|
||||
|
||||
err = sqlDB.PingContext(pingCtx)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("ping postgres: %w", err)
|
||||
}
|
||||
|
||||
// Ensure the PostgreSQL version is >=13.0.0!
|
||||
version, err := sqlDB.QueryContext(ctx, "SHOW server_version;")
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get postgres version: %w", err)
|
||||
}
|
||||
if !version.Next() {
|
||||
return nil, xerrors.Errorf("no rows returned for version select")
|
||||
}
|
||||
var versionStr string
|
||||
err = version.Scan(&versionStr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("scan version: %w", err)
|
||||
}
|
||||
_ = version.Close()
|
||||
versionStr = strings.Split(versionStr, " ")[0]
|
||||
if semver.Compare("v"+versionStr, "v13") < 0 {
|
||||
return nil, xerrors.New("PostgreSQL version must be v13.0.0 or higher!")
|
||||
}
|
||||
logger.Debug(ctx, "connected to postgresql", slog.F("version", versionStr))
|
||||
|
||||
err = migrations.Up(sqlDB)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("migrate up: %w", err)
|
||||
}
|
||||
// The default is 0 but the request will fail with a 500 if the DB
|
||||
// cannot accept new connections, so we try to limit that here.
|
||||
// Requests will wait for a new connection instead of a hard error
|
||||
// if a limit is set.
|
||||
sqlDB.SetMaxOpenConns(10)
|
||||
// Allow a max of 3 idle connections at a time. Lower values end up
|
||||
// creating a lot of connection churn. Since each connection uses about
|
||||
// 10MB of memory, we're allocating 30MB to Postgres connections per
|
||||
// replica, but is better than causing Postgres to spawn a thread 15-20
|
||||
// times/sec. PGBouncer's transaction pooling is not the greatest so
|
||||
// it's not optimal for us to deploy.
|
||||
//
|
||||
// This was set to 10 before we started doing HA deployments, but 3 was
|
||||
// later determined to be a better middle ground as to not use up all
|
||||
// of PGs default connection limit while simultaneously avoiding a lot
|
||||
// of connection churn.
|
||||
sqlDB.SetMaxIdleConns(3)
|
||||
|
||||
ok = true
|
||||
return sqlDB, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
//go:build !slim
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sort"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"cdr.dev/slog"
|
||||
"cdr.dev/slog/sloggers/sloghuman"
|
||||
"github.com/coder/coder/cli/cliui"
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/gitsshkey"
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
"github.com/coder/coder/coderd/rbac"
|
||||
"github.com/coder/coder/coderd/userpassword"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func newCreateAdminUserCommand() *cobra.Command {
|
||||
var (
|
||||
newUserDBURL string
|
||||
newUserSSHKeygenAlgorithm string
|
||||
newUserUsername string
|
||||
newUserEmail string
|
||||
newUserPassword string
|
||||
)
|
||||
createAdminUserCommand := &cobra.Command{
|
||||
Use: "create-admin-user",
|
||||
Short: "Create a new admin user with the given username, email and password and adds it to every organization.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Context()
|
||||
|
||||
sshKeygenAlgorithm, err := gitsshkey.ParseAlgorithm(newUserSSHKeygenAlgorithm)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parse ssh keygen algorithm %q: %w", newUserSSHKeygenAlgorithm, err)
|
||||
}
|
||||
|
||||
if val, exists := os.LookupEnv("CODER_POSTGRES_URL"); exists {
|
||||
newUserDBURL = val
|
||||
}
|
||||
if val, exists := os.LookupEnv("CODER_SSH_KEYGEN_ALGORITHM"); exists {
|
||||
newUserSSHKeygenAlgorithm = val
|
||||
}
|
||||
if val, exists := os.LookupEnv("CODER_USERNAME"); exists {
|
||||
newUserUsername = val
|
||||
}
|
||||
if val, exists := os.LookupEnv("CODER_EMAIL"); exists {
|
||||
newUserEmail = val
|
||||
}
|
||||
if val, exists := os.LookupEnv("CODER_PASSWORD"); exists {
|
||||
newUserPassword = val
|
||||
}
|
||||
|
||||
cfg := createConfig(cmd)
|
||||
logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()))
|
||||
if ok, _ := cmd.Flags().GetBool(varVerbose); ok {
|
||||
logger = logger.Leveled(slog.LevelDebug)
|
||||
}
|
||||
|
||||
ctx, cancel := signal.NotifyContext(ctx, InterruptSignals...)
|
||||
defer cancel()
|
||||
|
||||
if newUserDBURL == "" {
|
||||
cmd.Printf("Using built-in PostgreSQL (%s)\n", cfg.PostgresPath())
|
||||
url, closePg, err := startBuiltinPostgres(ctx, cfg, logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = closePg()
|
||||
}()
|
||||
newUserDBURL = url
|
||||
}
|
||||
|
||||
sqlDB, err := connectToPostgres(ctx, logger, "postgres", newUserDBURL)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("connect to postgres: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = sqlDB.Close()
|
||||
}()
|
||||
db := database.New(sqlDB)
|
||||
|
||||
validateInputs := func(username, email, password string) error {
|
||||
// Use the validator tags so we match the API's validation.
|
||||
req := codersdk.CreateUserRequest{
|
||||
Username: "username",
|
||||
Email: "email@coder.com",
|
||||
Password: "ValidPa$$word123!",
|
||||
OrganizationID: uuid.New(),
|
||||
}
|
||||
if username != "" {
|
||||
req.Username = username
|
||||
}
|
||||
if email != "" {
|
||||
req.Email = email
|
||||
}
|
||||
if password != "" {
|
||||
req.Password = password
|
||||
}
|
||||
|
||||
return httpapi.Validate.Struct(req)
|
||||
}
|
||||
|
||||
if newUserUsername == "" {
|
||||
newUserUsername, err = cliui.Prompt(cmd, cliui.PromptOptions{
|
||||
Text: "Username",
|
||||
Validate: func(val string) error {
|
||||
if val == "" {
|
||||
return xerrors.New("username cannot be empty")
|
||||
}
|
||||
return validateInputs(val, "", "")
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if newUserEmail == "" {
|
||||
newUserEmail, err = cliui.Prompt(cmd, cliui.PromptOptions{
|
||||
Text: "Email",
|
||||
Validate: func(val string) error {
|
||||
if val == "" {
|
||||
return xerrors.New("email cannot be empty")
|
||||
}
|
||||
return validateInputs("", val, "")
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if newUserPassword == "" {
|
||||
newUserPassword, err = cliui.Prompt(cmd, cliui.PromptOptions{
|
||||
Text: "Password",
|
||||
Secret: true,
|
||||
Validate: func(val string) error {
|
||||
if val == "" {
|
||||
return xerrors.New("password cannot be empty")
|
||||
}
|
||||
return validateInputs("", "", val)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prompt again.
|
||||
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
|
||||
Text: "Confirm password",
|
||||
Secret: true,
|
||||
Validate: func(val string) error {
|
||||
if val != newUserPassword {
|
||||
return xerrors.New("passwords do not match")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = validateInputs(newUserUsername, newUserEmail, newUserPassword)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("validate inputs: %w", err)
|
||||
}
|
||||
|
||||
hashedPassword, err := userpassword.Hash(newUserPassword)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("hash password: %w", err)
|
||||
}
|
||||
|
||||
// Create the user.
|
||||
var newUser database.User
|
||||
err = db.InTx(func(tx database.Store) error {
|
||||
orgs, err := tx.GetOrganizations(ctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get organizations: %w", err)
|
||||
}
|
||||
|
||||
// Sort organizations by name so that test output is consistent.
|
||||
sort.Slice(orgs, func(i, j int) bool {
|
||||
return orgs[i].Name < orgs[j].Name
|
||||
})
|
||||
|
||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Creating user...")
|
||||
newUser, err = tx.InsertUser(ctx, database.InsertUserParams{
|
||||
ID: uuid.New(),
|
||||
Email: newUserEmail,
|
||||
Username: newUserUsername,
|
||||
HashedPassword: []byte(hashedPassword),
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
RBACRoles: []string{rbac.RoleOwner()},
|
||||
LoginType: database.LoginTypePassword,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert user: %w", err)
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Generating user SSH key...")
|
||||
privateKey, publicKey, err := gitsshkey.Generate(sshKeygenAlgorithm)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("generate user gitsshkey: %w", err)
|
||||
}
|
||||
_, err = tx.InsertGitSSHKey(ctx, database.InsertGitSSHKeyParams{
|
||||
UserID: newUser.ID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
PrivateKey: privateKey,
|
||||
PublicKey: publicKey,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert user gitsshkey: %w", err)
|
||||
}
|
||||
|
||||
for _, org := range orgs {
|
||||
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Adding user to organization %q (%s) as admin...\n", org.Name, org.ID.String())
|
||||
_, err := tx.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
|
||||
OrganizationID: org.ID,
|
||||
UserID: newUser.ID,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
Roles: []string{rbac.RoleOrgAdmin(org.ID)},
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert organization member: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "")
|
||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "User created successfully.")
|
||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "ID: "+newUser.ID.String())
|
||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Username: "+newUser.Username)
|
||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Email: "+newUser.Email)
|
||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Password: ********")
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
createAdminUserCommand.Flags().StringVar(&newUserDBURL, "postgres-url", "", "URL of a PostgreSQL database. If empty, the built-in PostgreSQL deployment will be used (Coder must not be already running in this case). Consumes $CODER_POSTGRES_URL.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserSSHKeygenAlgorithm, "ssh-keygen-algorithm", "ed25519", "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\". Consumes $CODER_SSH_KEYGEN_ALGORITHM.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserUsername, "username", "", "The username of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_USERNAME.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserEmail, "email", "", "The email of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_EMAIL.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserPassword, "password", "", "The password of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_PASSWORD.")
|
||||
|
||||
return createAdminUserCommand
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
package cli_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/database/postgres"
|
||||
"github.com/coder/coder/coderd/rbac"
|
||||
"github.com/coder/coder/coderd/userpassword"
|
||||
"github.com/coder/coder/pty/ptytest"
|
||||
"github.com/coder/coder/testutil"
|
||||
)
|
||||
|
||||
//nolint:paralleltest, tparallel
|
||||
func TestServerCreateAdminUser(t *testing.T) {
|
||||
const (
|
||||
username = "dean"
|
||||
email = "dean@example.com"
|
||||
password = "SecurePa$$word123"
|
||||
)
|
||||
|
||||
verifyUser := func(t *testing.T, dbURL, username, email, password string) {
|
||||
t.Helper()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
sqlDB, err := sql.Open("postgres", dbURL)
|
||||
require.NoError(t, err)
|
||||
defer sqlDB.Close()
|
||||
db := database.New(sqlDB)
|
||||
|
||||
pingCtx, pingCancel := context.WithTimeout(ctx, testutil.WaitShort)
|
||||
defer pingCancel()
|
||||
_, err = db.Ping(pingCtx)
|
||||
require.NoError(t, err, "ping db")
|
||||
|
||||
user, err := db.GetUserByEmailOrUsername(ctx, database.GetUserByEmailOrUsernameParams{
|
||||
Email: email,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, username, user.Username, "username does not match")
|
||||
require.Equal(t, email, user.Email, "email does not match")
|
||||
|
||||
ok, err := userpassword.Compare(string(user.HashedPassword), password)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok, "password does not match")
|
||||
|
||||
require.EqualValues(t, []string{rbac.RoleOwner()}, user.RBACRoles, "user does not have owner role")
|
||||
|
||||
// Check that user is admin in every org.
|
||||
orgs, err := db.GetOrganizations(ctx)
|
||||
require.NoError(t, err)
|
||||
orgIDs := make(map[uuid.UUID]struct{}, len(orgs))
|
||||
for _, org := range orgs {
|
||||
orgIDs[org.ID] = struct{}{}
|
||||
}
|
||||
|
||||
orgMemberships, err := db.GetOrganizationMembershipsByUserID(ctx, user.ID)
|
||||
require.NoError(t, err)
|
||||
orgIDs2 := make(map[uuid.UUID]struct{}, len(orgMemberships))
|
||||
for _, membership := range orgMemberships {
|
||||
orgIDs2[membership.OrganizationID] = struct{}{}
|
||||
assert.Equal(t, []string{rbac.RoleOrgAdmin(membership.OrganizationID)}, membership.Roles, "user is not org admin")
|
||||
}
|
||||
|
||||
require.Equal(t, orgIDs, orgIDs2, "user is not in all orgs")
|
||||
}
|
||||
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if runtime.GOOS != "linux" || testing.Short() {
|
||||
// Skip on non-Linux because it spawns a PostgreSQL instance.
|
||||
t.SkipNow()
|
||||
}
|
||||
connectionURL, closeFunc, err := postgres.Open()
|
||||
require.NoError(t, err)
|
||||
defer closeFunc()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
||||
sqlDB, err := sql.Open("postgres", connectionURL)
|
||||
require.NoError(t, err)
|
||||
defer sqlDB.Close()
|
||||
db := database.New(sqlDB)
|
||||
|
||||
pingCtx, pingCancel := context.WithTimeout(ctx, testutil.WaitShort)
|
||||
defer pingCancel()
|
||||
_, err = db.Ping(pingCtx)
|
||||
require.NoError(t, err, "ping db")
|
||||
|
||||
// Insert a few orgs.
|
||||
org1Name, org1ID := "org1", uuid.New()
|
||||
org2Name, org2ID := "org2", uuid.New()
|
||||
_, err = db.InsertOrganization(ctx, database.InsertOrganizationParams{
|
||||
ID: org1ID,
|
||||
Name: org1Name,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = db.InsertOrganization(ctx, database.InsertOrganizationParams{
|
||||
ID: org2ID,
|
||||
Name: org2Name,
|
||||
CreatedAt: database.Now(),
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
root, _ := clitest.New(t,
|
||||
"server", "create-admin-user",
|
||||
"--postgres-url", connectionURL,
|
||||
"--ssh-keygen-algorithm", "ed25519",
|
||||
"--username", username,
|
||||
"--email", email,
|
||||
"--password", password,
|
||||
)
|
||||
pty := ptytest.New(t)
|
||||
root.SetOutput(pty.Output())
|
||||
root.SetErr(pty.Output())
|
||||
errC := make(chan error, 1)
|
||||
go func() {
|
||||
err := root.ExecuteContext(ctx)
|
||||
t.Log("root.ExecuteContext() returned:", err)
|
||||
errC <- err
|
||||
}()
|
||||
|
||||
pty.ExpectMatch("Creating user...")
|
||||
pty.ExpectMatch("Generating user SSH key...")
|
||||
pty.ExpectMatch(fmt.Sprintf("Adding user to organization %q (%s) as admin...", org1Name, org1ID.String()))
|
||||
pty.ExpectMatch(fmt.Sprintf("Adding user to organization %q (%s) as admin...", org2Name, org2ID.String()))
|
||||
pty.ExpectMatch("User created successfully.")
|
||||
pty.ExpectMatch(username)
|
||||
pty.ExpectMatch(email)
|
||||
pty.ExpectMatch("****")
|
||||
|
||||
require.NoError(t, <-errC)
|
||||
|
||||
verifyUser(t, connectionURL, username, email, password)
|
||||
})
|
||||
|
||||
//nolint:paralleltest
|
||||
t.Run("Env", func(t *testing.T) {
|
||||
if runtime.GOOS != "linux" || testing.Short() {
|
||||
// Skip on non-Linux because it spawns a PostgreSQL instance.
|
||||
t.SkipNow()
|
||||
}
|
||||
connectionURL, closeFunc, err := postgres.Open()
|
||||
require.NoError(t, err)
|
||||
defer closeFunc()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
||||
t.Setenv("CODER_POSTGRES_URL", connectionURL)
|
||||
t.Setenv("CODER_SSH_KEYGEN_ALGORITHM", "ecdsa")
|
||||
t.Setenv("CODER_USERNAME", username)
|
||||
t.Setenv("CODER_EMAIL", email)
|
||||
t.Setenv("CODER_PASSWORD", password)
|
||||
|
||||
root, _ := clitest.New(t, "server", "create-admin-user")
|
||||
pty := ptytest.New(t)
|
||||
root.SetOutput(pty.Output())
|
||||
root.SetErr(pty.Output())
|
||||
errC := make(chan error, 1)
|
||||
go func() {
|
||||
err := root.ExecuteContext(ctx)
|
||||
t.Log("root.ExecuteContext() returned:", err)
|
||||
errC <- err
|
||||
}()
|
||||
|
||||
pty.ExpectMatch("User created successfully.")
|
||||
pty.ExpectMatch(username)
|
||||
pty.ExpectMatch(email)
|
||||
pty.ExpectMatch("****")
|
||||
|
||||
require.NoError(t, <-errC)
|
||||
|
||||
verifyUser(t, connectionURL, username, email, password)
|
||||
})
|
||||
|
||||
t.Run("Stdin", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if runtime.GOOS != "linux" || testing.Short() {
|
||||
// Skip on non-Linux because it spawns a PostgreSQL instance.
|
||||
t.SkipNow()
|
||||
}
|
||||
connectionURL, closeFunc, err := postgres.Open()
|
||||
require.NoError(t, err)
|
||||
defer closeFunc()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
||||
root, _ := clitest.New(t,
|
||||
"server", "create-admin-user",
|
||||
"--postgres-url", connectionURL,
|
||||
"--ssh-keygen-algorithm", "rsa4096",
|
||||
)
|
||||
pty := ptytest.New(t)
|
||||
root.SetIn(pty.Input())
|
||||
root.SetOutput(pty.Output())
|
||||
root.SetErr(pty.Output())
|
||||
errC := make(chan error, 1)
|
||||
go func() {
|
||||
err := root.ExecuteContext(ctx)
|
||||
t.Log("root.ExecuteContext() returned:", err)
|
||||
errC <- err
|
||||
}()
|
||||
|
||||
pty.ExpectMatch("> Username")
|
||||
pty.WriteLine(username)
|
||||
pty.ExpectMatch("> Email")
|
||||
pty.WriteLine(email)
|
||||
pty.ExpectMatch("> Password")
|
||||
pty.WriteLine(password)
|
||||
pty.ExpectMatch("> Confirm password")
|
||||
pty.WriteLine(password)
|
||||
|
||||
pty.ExpectMatch("User created successfully.")
|
||||
pty.ExpectMatch(username)
|
||||
pty.ExpectMatch(email)
|
||||
pty.ExpectMatch("****")
|
||||
|
||||
require.NoError(t, <-errC)
|
||||
|
||||
verifyUser(t, connectionURL, username, email, password)
|
||||
})
|
||||
|
||||
t.Run("Validates", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if runtime.GOOS != "linux" || testing.Short() {
|
||||
// Skip on non-Linux because it spawns a PostgreSQL instance.
|
||||
t.SkipNow()
|
||||
}
|
||||
connectionURL, closeFunc, err := postgres.Open()
|
||||
require.NoError(t, err)
|
||||
defer closeFunc()
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
||||
root, _ := clitest.New(t,
|
||||
"server", "create-admin-user",
|
||||
"--postgres-url", connectionURL,
|
||||
"--ssh-keygen-algorithm", "rsa4096",
|
||||
"--username", "$",
|
||||
"--email", "not-an-email",
|
||||
"--password", "x",
|
||||
)
|
||||
pty := ptytest.New(t)
|
||||
root.SetOutput(pty.Output())
|
||||
root.SetErr(pty.Output())
|
||||
|
||||
err = root.ExecuteContext(ctx)
|
||||
require.Error(t, err)
|
||||
require.ErrorContains(t, err, "'email' failed on the 'email' tag")
|
||||
require.ErrorContains(t, err, "'username' failed on the 'username' tag")
|
||||
})
|
||||
}
|
|
@ -47,12 +47,34 @@ func Server(vip *viper.Viper, _ func(context.Context, *coderd.Options) (*coderd.
|
|||
},
|
||||
}
|
||||
|
||||
var (
|
||||
newUserDBURL string
|
||||
newUserSSHKeygenAlgorithm string
|
||||
newUserUsername string
|
||||
newUserEmail string
|
||||
newUserPassword string
|
||||
)
|
||||
createAdminUserCommand := &cobra.Command{
|
||||
Use: "create-admin-user",
|
||||
Short: "Create a new admin user with the given username, email and password and adds it to every organization.",
|
||||
Hidden: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
serverUnsupported(cmd.ErrOrStderr())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// We still have to attach the flags to the commands so users don't get
|
||||
// an error when they try to use them.
|
||||
postgresBuiltinURLCmd.Flags().BoolVar(&pgRawURL, "raw-url", false, "Output the raw connection URL instead of a psql command.")
|
||||
postgresBuiltinServeCmd.Flags().BoolVar(&pgRawURL, "raw-url", false, "Output the raw connection URL instead of a psql command.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserDBURL, "postgres-url", "", "URL of a PostgreSQL database. If empty, the built-in PostgreSQL deployment will be used (Coder must not be already running in this case). Consumes $CODER_POSTGRES_URL.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserSSHKeygenAlgorithm, "ssh-keygen-algorithm", "ed25519", "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\". Consumes $CODER_SSH_KEYGEN_ALGORITHM.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserUsername, "username", "", "The username of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_USERNAME.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserEmail, "email", "", "The email of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_EMAIL.")
|
||||
createAdminUserCommand.Flags().StringVar(&newUserPassword, "password", "", "The password of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_PASSWORD.")
|
||||
|
||||
root.AddCommand(postgresBuiltinURLCmd, postgresBuiltinServeCmd)
|
||||
root.AddCommand(postgresBuiltinURLCmd, postgresBuiltinServeCmd, createAdminUserCommand)
|
||||
|
||||
deployment.AttachFlags(root.Flags(), vip, false)
|
||||
|
||||
|
|
|
@ -6,316 +6,362 @@ Usage:
|
|||
coder server [command]
|
||||
|
||||
Commands:
|
||||
create-admin-user Create a new admin user with the given username, email and password and adds it to every organization.
|
||||
postgres-builtin-serve Run the built-in PostgreSQL deployment.
|
||||
postgres-builtin-url Output the connection URL for the built-in PostgreSQL deployment.
|
||||
|
||||
Flags:
|
||||
--access-url string External URL to access your deployment.
|
||||
This must be accessible by all
|
||||
provisioned workspaces.
|
||||
Consumes $CODER_ACCESS_URL
|
||||
--api-rate-limit int Maximum number of requests per minute
|
||||
allowed to the API per user, or per IP
|
||||
address for unauthenticated users.
|
||||
Negative values mean no rate limit. Some
|
||||
API endpoints have separate strict rate
|
||||
limits regardless of this value to
|
||||
prevent denial-of-service or brute force
|
||||
attacks.
|
||||
Consumes $CODER_API_RATE_LIMIT (default 512)
|
||||
--cache-dir string The directory to cache temporary files.
|
||||
If unspecified and $CACHE_DIRECTORY is
|
||||
set, it will be used for compatibility
|
||||
with systemd.
|
||||
Consumes $CODER_CACHE_DIRECTORY (default
|
||||
"~/.cache/coder")
|
||||
--dangerous-allow-path-app-sharing Allow workspace apps that are not served
|
||||
from subdomains to be shared. Path-based
|
||||
app sharing is DISABLED by default for
|
||||
security purposes. Path-based apps can
|
||||
make requests to the Coder API and pose a
|
||||
security risk when the workspace serves
|
||||
malicious JavaScript. Path-based apps can
|
||||
be disabled entirely with
|
||||
--disable-path-apps for further security.
|
||||
Consumes
|
||||
$CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
|
||||
--dangerous-allow-path-app-site-owner-access Allow site-owners to access workspace
|
||||
apps from workspaces they do not own.
|
||||
Owners cannot access path-based apps they
|
||||
do not own by default. Path-based apps
|
||||
can make requests to the Coder API and
|
||||
pose a security risk when the workspace
|
||||
serves malicious JavaScript. Path-based
|
||||
apps can be disabled entirely with
|
||||
--disable-path-apps for further security.
|
||||
Consumes
|
||||
$CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
|
||||
--dangerous-disable-rate-limits Disables all rate limits. This is not
|
||||
recommended in production.
|
||||
Consumes $CODER_RATE_LIMIT_DISABLE_ALL
|
||||
--derp-config-path string Path to read a DERP mapping from. See:
|
||||
https://tailscale.com/kb/1118/custom-derp-servers/
|
||||
Consumes $CODER_DERP_CONFIG_PATH
|
||||
--derp-config-url string URL to fetch a DERP mapping on startup.
|
||||
See:
|
||||
https://tailscale.com/kb/1118/custom-derp-servers/
|
||||
Consumes $CODER_DERP_CONFIG_URL
|
||||
--derp-server-enable Whether to enable or disable the embedded
|
||||
DERP relay server.
|
||||
Consumes $CODER_DERP_SERVER_ENABLE
|
||||
(default true)
|
||||
--derp-server-region-code string Region code to use for the embedded DERP
|
||||
server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_CODE
|
||||
(default "coder")
|
||||
--derp-server-region-id int Region ID to use for the embedded DERP
|
||||
server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_ID
|
||||
(default 999)
|
||||
--derp-server-region-name string Region name that for the embedded DERP
|
||||
server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_NAME
|
||||
(default "Coder Embedded Relay")
|
||||
--derp-server-stun-addresses strings Addresses for STUN servers to establish
|
||||
P2P connections. Set empty to disable P2P
|
||||
connections.
|
||||
Consumes
|
||||
$CODER_DERP_SERVER_STUN_ADDRESSES
|
||||
(default [stun.l.google.com:19302])
|
||||
--disable-path-apps Disable workspace apps that are not
|
||||
served from subdomains. Path-based apps
|
||||
can make requests to the Coder API and
|
||||
pose a security risk when the workspace
|
||||
serves malicious JavaScript. This is
|
||||
recommended for security purposes if a
|
||||
--wildcard-access-url is configured.
|
||||
Consumes $CODER_DISABLE_PATH_APPS
|
||||
--disable-session-expiry-refresh Disable automatic session expiry bumping
|
||||
due to activity. This forces all sessions
|
||||
to become invalid after the session
|
||||
expiry duration has been reached.
|
||||
Consumes $CODER_DISABLE_SESSION_EXPIRY_REFRESH
|
||||
--experiments strings Enable one or more experiments. These are
|
||||
not ready for production. Separate
|
||||
multiple experiments with commas, or
|
||||
enter '*' to opt-in to all available
|
||||
experiments.
|
||||
Consumes $CODER_EXPERIMENTS
|
||||
-h, --help help for server
|
||||
--http-address string HTTP bind address of the server. Unset to
|
||||
disable the HTTP endpoint.
|
||||
Consumes $CODER_HTTP_ADDRESS (default
|
||||
"127.0.0.1:3000")
|
||||
--log-human string Output human-readable logs to a given
|
||||
file.
|
||||
Consumes $CODER_LOGGING_HUMAN (default
|
||||
"/dev/stderr")
|
||||
--log-json string Output JSON logs to a given file.
|
||||
Consumes $CODER_LOGGING_JSON
|
||||
--log-stackdriver string Output Stackdriver compatible logs to a
|
||||
given file.
|
||||
Consumes $CODER_LOGGING_STACKDRIVER
|
||||
--max-token-lifetime duration The maximum lifetime duration users can
|
||||
specify when creating an API token.
|
||||
Consumes $CODER_MAX_TOKEN_LIFETIME
|
||||
(default 720h0m0s)
|
||||
--oauth2-github-allow-everyone Allow all logins, setting this option
|
||||
means allowed orgs and teams must be
|
||||
empty.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
|
||||
--oauth2-github-allow-signups Whether new users can sign up with
|
||||
GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
|
||||
--oauth2-github-allowed-orgs strings Organizations the user must be a member
|
||||
of to Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_ORGS
|
||||
--oauth2-github-allowed-teams strings Teams inside organizations the user must
|
||||
be a member of to Login with GitHub.
|
||||
Structured as:
|
||||
<organization-name>/<team-slug>.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_TEAMS
|
||||
--oauth2-github-client-id string Client ID for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_CLIENT_ID
|
||||
--oauth2-github-client-secret string Client secret for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_CLIENT_SECRET
|
||||
--oauth2-github-enterprise-base-url string Base URL of a GitHub Enterprise
|
||||
deployment to use for Login with GitHub.
|
||||
Consumes
|
||||
$CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL
|
||||
--oidc-allow-signups Whether new users can sign up with OIDC.
|
||||
Consumes $CODER_OIDC_ALLOW_SIGNUPS
|
||||
(default true)
|
||||
--oidc-client-id string Client ID to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_CLIENT_ID
|
||||
--oidc-client-secret string Client secret to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_CLIENT_SECRET
|
||||
--oidc-email-domain strings Email domains that clients logging in
|
||||
with OIDC must match.
|
||||
Consumes $CODER_OIDC_EMAIL_DOMAIN
|
||||
--oidc-icon-url string URL pointing to the icon to use on the
|
||||
OepnID Connect login button
|
||||
Consumes $CODER_OIDC_ICON_URL
|
||||
--oidc-ignore-email-verified Ignore the email_verified claim from the
|
||||
upstream provider.
|
||||
Consumes $CODER_OIDC_IGNORE_EMAIL_VERIFIED
|
||||
--oidc-issuer-url string Issuer URL to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_ISSUER_URL
|
||||
--oidc-scopes strings Scopes to grant when authenticating with
|
||||
OIDC.
|
||||
Consumes $CODER_OIDC_SCOPES (default
|
||||
[openid,profile,email])
|
||||
--oidc-sign-in-text string The text to show on the OpenID Connect
|
||||
sign in button
|
||||
Consumes $CODER_OIDC_SIGN_IN_TEXT
|
||||
(default "OpenID Connect")
|
||||
--oidc-username-field string OIDC claim field to use as the username.
|
||||
Consumes $CODER_OIDC_USERNAME_FIELD
|
||||
(default "preferred_username")
|
||||
--postgres-url string URL of a PostgreSQL database. If empty,
|
||||
PostgreSQL binaries will be downloaded
|
||||
from Maven
|
||||
(https://repo1.maven.org/maven2) and
|
||||
store all data in the config root. Access
|
||||
the built-in database with "coder server
|
||||
postgres-builtin-url".
|
||||
Consumes $CODER_PG_CONNECTION_URL
|
||||
--pprof-address string The bind address to serve pprof.
|
||||
Consumes $CODER_PPROF_ADDRESS (default
|
||||
"127.0.0.1:6060")
|
||||
--pprof-enable Serve pprof metrics on the address
|
||||
defined by pprof address.
|
||||
Consumes $CODER_PPROF_ENABLE
|
||||
--prometheus-address string The bind address to serve prometheus
|
||||
metrics.
|
||||
Consumes $CODER_PROMETHEUS_ADDRESS
|
||||
(default "127.0.0.1:2112")
|
||||
--prometheus-enable Serve prometheus metrics on the address
|
||||
defined by prometheus address.
|
||||
Consumes $CODER_PROMETHEUS_ENABLE
|
||||
--provisioner-daemon-poll-interval duration Time to wait before polling for a new
|
||||
job.
|
||||
Consumes
|
||||
$CODER_PROVISIONER_DAEMON_POLL_INTERVAL
|
||||
(default 1s)
|
||||
--provisioner-daemon-poll-jitter duration Random jitter added to the poll interval.
|
||||
Consumes
|
||||
$CODER_PROVISIONER_DAEMON_POLL_JITTER
|
||||
(default 100ms)
|
||||
--provisioner-daemons int Number of provisioner daemons to create
|
||||
on start. If builds are stuck in queued
|
||||
state for a long time, consider
|
||||
increasing this.
|
||||
Consumes $CODER_PROVISIONER_DAEMONS
|
||||
(default 3)
|
||||
--provisioner-force-cancel-interval duration Time to force cancel provisioning tasks
|
||||
that are stuck.
|
||||
Consumes
|
||||
$CODER_PROVISIONER_FORCE_CANCEL_INTERVAL
|
||||
(default 10m0s)
|
||||
--proxy-trusted-headers strings Headers to trust for forwarding IP
|
||||
addresses. e.g. Cf-Connecting-Ip,
|
||||
True-Client-Ip, X-Forwarded-For
|
||||
Consumes $CODER_PROXY_TRUSTED_HEADERS
|
||||
--proxy-trusted-origins strings Origin addresses to respect
|
||||
"proxy-trusted-headers". e.g.
|
||||
192.168.1.0/24
|
||||
Consumes $CODER_PROXY_TRUSTED_ORIGINS
|
||||
--redirect-to-access-url Specifies whether to redirect requests
|
||||
that do not match the access URL host.
|
||||
Consumes $CODER_REDIRECT_TO_ACCESS_URL
|
||||
--secure-auth-cookie Controls if the 'Secure' property is set
|
||||
on browser session cookies.
|
||||
Consumes $CODER_SECURE_AUTH_COOKIE
|
||||
--session-duration duration The token expiry duration for browser
|
||||
sessions. Sessions may last longer if
|
||||
they are actively making requests, but
|
||||
this functionality can be disabled via
|
||||
--disable-session-expiry-refresh.
|
||||
Consumes $CODER_MAX_SESSION_EXPIRY
|
||||
(default 24h0m0s)
|
||||
--ssh-keygen-algorithm string The algorithm to use for generating ssh
|
||||
keys. Accepted values are "ed25519",
|
||||
"ecdsa", or "rsa4096".
|
||||
Consumes $CODER_SSH_KEYGEN_ALGORITHM
|
||||
(default "ed25519")
|
||||
--swagger-enable Expose the swagger endpoint via /swagger.
|
||||
Consumes $CODER_SWAGGER_ENABLE
|
||||
--telemetry Whether telemetry is enabled or not.
|
||||
Coder collects anonymized usage data to
|
||||
help improve our product.
|
||||
Consumes $CODER_TELEMETRY_ENABLE
|
||||
--telemetry-trace Whether Opentelemetry traces are sent to
|
||||
Coder. Coder collects anonymized
|
||||
application tracing to help improve our
|
||||
product. Disabling telemetry also
|
||||
disables this option.
|
||||
Consumes $CODER_TELEMETRY_TRACE
|
||||
--tls-address string HTTPS bind address of the server.
|
||||
Consumes $CODER_TLS_ADDRESS (default
|
||||
"127.0.0.1:3443")
|
||||
--tls-cert-file strings Path to each certificate for TLS. It
|
||||
requires a PEM-encoded file. To configure
|
||||
the listener to use a CA certificate,
|
||||
concatenate the primary certificate and
|
||||
the CA certificate together. The primary
|
||||
certificate should appear first in the
|
||||
combined file.
|
||||
Consumes $CODER_TLS_CERT_FILE
|
||||
--tls-client-auth string Policy the server will follow for TLS
|
||||
Client Authentication. Accepted values
|
||||
are "none", "request", "require-any",
|
||||
"verify-if-given", or
|
||||
"require-and-verify".
|
||||
Consumes $CODER_TLS_CLIENT_AUTH (default
|
||||
"none")
|
||||
--tls-client-ca-file string PEM-encoded Certificate Authority file
|
||||
used for checking the authenticity of
|
||||
client
|
||||
Consumes $CODER_TLS_CLIENT_CA_FILE
|
||||
--tls-client-cert-file string Path to certificate for client TLS
|
||||
authentication. It requires a PEM-encoded
|
||||
file.
|
||||
Consumes $CODER_TLS_CLIENT_CERT_FILE
|
||||
--tls-client-key-file string Path to key for client TLS
|
||||
authentication. It requires a PEM-encoded
|
||||
file.
|
||||
Consumes $CODER_TLS_CLIENT_KEY_FILE
|
||||
--tls-enable Whether TLS will be enabled.
|
||||
Consumes $CODER_TLS_ENABLE
|
||||
--tls-key-file strings Paths to the private keys for each of the
|
||||
certificates. It requires a PEM-encoded
|
||||
file.
|
||||
Consumes $CODER_TLS_KEY_FILE
|
||||
--tls-min-version string Minimum supported version of TLS.
|
||||
Accepted values are "tls10", "tls11",
|
||||
"tls12" or "tls13"
|
||||
Consumes $CODER_TLS_MIN_VERSION (default
|
||||
"tls12")
|
||||
--trace Whether application tracing data is
|
||||
collected. It exports to a backend
|
||||
configured by environment variables. See:
|
||||
https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md
|
||||
Consumes $CODER_TRACE_ENABLE
|
||||
--trace-honeycomb-api-key string Enables trace exporting to Honeycomb.io
|
||||
using the provided API Key.
|
||||
Consumes $CODER_TRACE_HONEYCOMB_API_KEY
|
||||
--trace-logs Enables capturing of logs as events in
|
||||
traces. This is useful for debugging, but
|
||||
may result in a very large amount of
|
||||
events being sent to the tracing backend
|
||||
which may incur significant costs. If the
|
||||
verbose flag was supplied, debug-level
|
||||
logs will be included.
|
||||
Consumes $CODER_TRACE_CAPTURE_LOGS
|
||||
--update-check Periodically check for new releases of
|
||||
Coder and inform the owner. The check is
|
||||
performed once per day.
|
||||
Consumes $CODER_UPDATE_CHECK
|
||||
--wildcard-access-url string Specifies the wildcard hostname to use
|
||||
for workspace applications in the form
|
||||
"*.example.com".
|
||||
Consumes $CODER_WILDCARD_ACCESS_URL
|
||||
--access-url string External URL to access your
|
||||
deployment. This must be accessible
|
||||
by all provisioned workspaces.
|
||||
Consumes $CODER_ACCESS_URL
|
||||
--api-rate-limit int Maximum number of requests per
|
||||
minute allowed to the API per user,
|
||||
or per IP address for
|
||||
unauthenticated users. Negative
|
||||
values mean no rate limit. Some API
|
||||
endpoints have separate strict rate
|
||||
limits regardless of this value to
|
||||
prevent denial-of-service or brute
|
||||
force attacks.
|
||||
Consumes $CODER_API_RATE_LIMIT
|
||||
(default 512)
|
||||
--cache-dir string The directory to cache temporary
|
||||
files. If unspecified and
|
||||
$CACHE_DIRECTORY is set, it will be
|
||||
used for compatibility with systemd.
|
||||
Consumes $CODER_CACHE_DIRECTORY
|
||||
(default "~/.cache/coder")
|
||||
--dangerous-allow-path-app-sharing Allow workspace apps that are not
|
||||
served from subdomains to be shared.
|
||||
Path-based app sharing is DISABLED
|
||||
by default for security purposes.
|
||||
Path-based apps can make requests to
|
||||
the Coder API and pose a security
|
||||
risk when the workspace serves
|
||||
malicious JavaScript. Path-based
|
||||
apps can be disabled entirely with
|
||||
--disable-path-apps for further
|
||||
security.
|
||||
Consumes
|
||||
$CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
|
||||
--dangerous-allow-path-app-site-owner-access Allow site-owners to access
|
||||
workspace apps from workspaces they
|
||||
do not own. Owners cannot access
|
||||
path-based apps they do not own by
|
||||
default. Path-based apps can make
|
||||
requests to the Coder API and pose a
|
||||
security risk when the workspace
|
||||
serves malicious JavaScript.
|
||||
Path-based apps can be disabled
|
||||
entirely with --disable-path-apps
|
||||
for further security.
|
||||
Consumes
|
||||
$CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
|
||||
--dangerous-disable-rate-limits Disables all rate limits. This is
|
||||
not recommended in production.
|
||||
Consumes $CODER_RATE_LIMIT_DISABLE_ALL
|
||||
--derp-config-path string Path to read a DERP mapping from.
|
||||
See:
|
||||
https://tailscale.com/kb/1118/custom-derp-servers/
|
||||
Consumes $CODER_DERP_CONFIG_PATH
|
||||
--derp-config-url string URL to fetch a DERP mapping on
|
||||
startup. See:
|
||||
https://tailscale.com/kb/1118/custom-derp-servers/
|
||||
Consumes $CODER_DERP_CONFIG_URL
|
||||
--derp-server-enable Whether to enable or disable the
|
||||
embedded DERP relay server.
|
||||
Consumes $CODER_DERP_SERVER_ENABLE
|
||||
(default true)
|
||||
--derp-server-region-code string Region code to use for the embedded
|
||||
DERP server.
|
||||
Consumes
|
||||
$CODER_DERP_SERVER_REGION_CODE
|
||||
(default "coder")
|
||||
--derp-server-region-id int Region ID to use for the embedded
|
||||
DERP server.
|
||||
Consumes
|
||||
$CODER_DERP_SERVER_REGION_ID
|
||||
(default 999)
|
||||
--derp-server-region-name string Region name that for the embedded
|
||||
DERP server.
|
||||
Consumes
|
||||
$CODER_DERP_SERVER_REGION_NAME
|
||||
(default "Coder Embedded Relay")
|
||||
--derp-server-stun-addresses strings Addresses for STUN servers to
|
||||
establish P2P connections. Set empty
|
||||
to disable P2P connections.
|
||||
Consumes
|
||||
$CODER_DERP_SERVER_STUN_ADDRESSES
|
||||
(default [stun.l.google.com:19302])
|
||||
--disable-password-auth coder server create-admin Disable password authentication.
|
||||
This is recommended for security
|
||||
purposes in production deployments
|
||||
that rely on an identity provider.
|
||||
Any user with the owner role will be
|
||||
able to sign in with their password
|
||||
regardless of this setting to avoid
|
||||
potential lock out. If you are
|
||||
locked out of your account, you can
|
||||
use the coder server create-admin
|
||||
command to create a new admin user
|
||||
directly in the database.
|
||||
Consumes $CODER_DISABLE_PASSWORD_AUTH
|
||||
--disable-path-apps Disable workspace apps that are not
|
||||
served from subdomains. Path-based
|
||||
apps can make requests to the Coder
|
||||
API and pose a security risk when
|
||||
the workspace serves malicious
|
||||
JavaScript. This is recommended for
|
||||
security purposes if a
|
||||
--wildcard-access-url is configured.
|
||||
Consumes $CODER_DISABLE_PATH_APPS
|
||||
--disable-session-expiry-refresh Disable automatic session expiry
|
||||
bumping due to activity. This forces
|
||||
all sessions to become invalid after
|
||||
the session expiry duration has been
|
||||
reached.
|
||||
Consumes
|
||||
$CODER_DISABLE_SESSION_EXPIRY_REFRESH
|
||||
--experiments strings Enable one or more experiments.
|
||||
These are not ready for production.
|
||||
Separate multiple experiments with
|
||||
commas, or enter '*' to opt-in to
|
||||
all available experiments.
|
||||
Consumes $CODER_EXPERIMENTS
|
||||
-h, --help help for server
|
||||
--http-address string HTTP bind address of the server.
|
||||
Unset to disable the HTTP endpoint.
|
||||
Consumes $CODER_HTTP_ADDRESS
|
||||
(default "127.0.0.1:3000")
|
||||
--log-human string Output human-readable logs to a
|
||||
given file.
|
||||
Consumes $CODER_LOGGING_HUMAN
|
||||
(default "/dev/stderr")
|
||||
--log-json string Output JSON logs to a given file.
|
||||
Consumes $CODER_LOGGING_JSON
|
||||
--log-stackdriver string Output Stackdriver compatible logs
|
||||
to a given file.
|
||||
Consumes $CODER_LOGGING_STACKDRIVER
|
||||
--max-token-lifetime duration The maximum lifetime duration users
|
||||
can specify when creating an API
|
||||
token.
|
||||
Consumes $CODER_MAX_TOKEN_LIFETIME
|
||||
(default 720h0m0s)
|
||||
--oauth2-github-allow-everyone Allow all logins, setting this
|
||||
option means allowed orgs and teams
|
||||
must be empty.
|
||||
Consumes
|
||||
$CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
|
||||
--oauth2-github-allow-signups Whether new users can sign up with
|
||||
GitHub.
|
||||
Consumes
|
||||
$CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
|
||||
--oauth2-github-allowed-orgs strings Organizations the user must be a
|
||||
member of to Login with GitHub.
|
||||
Consumes
|
||||
$CODER_OAUTH2_GITHUB_ALLOWED_ORGS
|
||||
--oauth2-github-allowed-teams strings Teams inside organizations the user
|
||||
must be a member of to Login with
|
||||
GitHub. Structured as:
|
||||
<organization-name>/<team-slug>.
|
||||
Consumes
|
||||
$CODER_OAUTH2_GITHUB_ALLOWED_TEAMS
|
||||
--oauth2-github-client-id string Client ID for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_CLIENT_ID
|
||||
--oauth2-github-client-secret string Client secret for Login with GitHub.
|
||||
Consumes
|
||||
$CODER_OAUTH2_GITHUB_CLIENT_SECRET
|
||||
--oauth2-github-enterprise-base-url string Base URL of a GitHub Enterprise
|
||||
deployment to use for Login with
|
||||
GitHub.
|
||||
Consumes
|
||||
$CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL
|
||||
--oidc-allow-signups Whether new users can sign up with
|
||||
OIDC.
|
||||
Consumes $CODER_OIDC_ALLOW_SIGNUPS
|
||||
(default true)
|
||||
--oidc-client-id string Client ID to use for Login with
|
||||
OIDC.
|
||||
Consumes $CODER_OIDC_CLIENT_ID
|
||||
--oidc-client-secret string Client secret to use for Login with
|
||||
OIDC.
|
||||
Consumes $CODER_OIDC_CLIENT_SECRET
|
||||
--oidc-email-domain strings Email domains that clients logging
|
||||
in with OIDC must match.
|
||||
Consumes $CODER_OIDC_EMAIL_DOMAIN
|
||||
--oidc-icon-url string URL pointing to the icon to use on
|
||||
the OepnID Connect login button
|
||||
Consumes $CODER_OIDC_ICON_URL
|
||||
--oidc-ignore-email-verified Ignore the email_verified claim from
|
||||
the upstream provider.
|
||||
Consumes
|
||||
$CODER_OIDC_IGNORE_EMAIL_VERIFIED
|
||||
--oidc-issuer-url string Issuer URL to use for Login with
|
||||
OIDC.
|
||||
Consumes $CODER_OIDC_ISSUER_URL
|
||||
--oidc-scopes strings Scopes to grant when authenticating
|
||||
with OIDC.
|
||||
Consumes $CODER_OIDC_SCOPES (default
|
||||
[openid,profile,email])
|
||||
--oidc-sign-in-text string The text to show on the OpenID
|
||||
Connect sign in button
|
||||
Consumes $CODER_OIDC_SIGN_IN_TEXT
|
||||
(default "OpenID Connect")
|
||||
--oidc-username-field string OIDC claim field to use as the
|
||||
username.
|
||||
Consumes $CODER_OIDC_USERNAME_FIELD
|
||||
(default "preferred_username")
|
||||
--postgres-url string URL of a PostgreSQL database. If
|
||||
empty, PostgreSQL binaries will be
|
||||
downloaded from Maven
|
||||
(https://repo1.maven.org/maven2) and
|
||||
store all data in the config root.
|
||||
Access the built-in database with
|
||||
"coder server postgres-builtin-url".
|
||||
Consumes $CODER_PG_CONNECTION_URL
|
||||
--pprof-address string The bind address to serve pprof.
|
||||
Consumes $CODER_PPROF_ADDRESS
|
||||
(default "127.0.0.1:6060")
|
||||
--pprof-enable Serve pprof metrics on the address
|
||||
defined by pprof address.
|
||||
Consumes $CODER_PPROF_ENABLE
|
||||
--prometheus-address string The bind address to serve prometheus
|
||||
metrics.
|
||||
Consumes $CODER_PROMETHEUS_ADDRESS
|
||||
(default "127.0.0.1:2112")
|
||||
--prometheus-enable Serve prometheus metrics on the
|
||||
address defined by prometheus
|
||||
address.
|
||||
Consumes $CODER_PROMETHEUS_ENABLE
|
||||
--provisioner-daemon-poll-interval duration Time to wait before polling for a
|
||||
new job.
|
||||
Consumes
|
||||
$CODER_PROVISIONER_DAEMON_POLL_INTERVAL (default 1s)
|
||||
--provisioner-daemon-poll-jitter duration Random jitter added to the poll
|
||||
interval.
|
||||
Consumes
|
||||
$CODER_PROVISIONER_DAEMON_POLL_JITTER (default 100ms)
|
||||
--provisioner-daemons int Number of provisioner daemons to
|
||||
create on start. If builds are stuck
|
||||
in queued state for a long time,
|
||||
consider increasing this.
|
||||
Consumes $CODER_PROVISIONER_DAEMONS
|
||||
(default 3)
|
||||
--provisioner-force-cancel-interval duration Time to force cancel provisioning
|
||||
tasks that are stuck.
|
||||
Consumes
|
||||
$CODER_PROVISIONER_FORCE_CANCEL_INTERVAL (default 10m0s)
|
||||
--proxy-trusted-headers strings Headers to trust for forwarding IP
|
||||
addresses. e.g. Cf-Connecting-Ip,
|
||||
True-Client-Ip, X-Forwarded-For
|
||||
Consumes $CODER_PROXY_TRUSTED_HEADERS
|
||||
--proxy-trusted-origins strings Origin addresses to respect
|
||||
"proxy-trusted-headers". e.g.
|
||||
192.168.1.0/24
|
||||
Consumes $CODER_PROXY_TRUSTED_ORIGINS
|
||||
--redirect-to-access-url Specifies whether to redirect
|
||||
requests that do not match the
|
||||
access URL host.
|
||||
Consumes $CODER_REDIRECT_TO_ACCESS_URL
|
||||
--secure-auth-cookie Controls if the 'Secure' property is
|
||||
set on browser session cookies.
|
||||
Consumes $CODER_SECURE_AUTH_COOKIE
|
||||
--session-duration duration The token expiry duration for
|
||||
browser sessions. Sessions may last
|
||||
longer if they are actively making
|
||||
requests, but this functionality can
|
||||
be disabled via
|
||||
--disable-session-expiry-refresh.
|
||||
Consumes $CODER_MAX_SESSION_EXPIRY
|
||||
(default 24h0m0s)
|
||||
--ssh-keygen-algorithm string The algorithm to use for generating
|
||||
ssh keys. Accepted values are
|
||||
"ed25519", "ecdsa", or "rsa4096".
|
||||
Consumes $CODER_SSH_KEYGEN_ALGORITHM
|
||||
(default "ed25519")
|
||||
--swagger-enable Expose the swagger endpoint via
|
||||
/swagger.
|
||||
Consumes $CODER_SWAGGER_ENABLE
|
||||
--telemetry Whether telemetry is enabled or not.
|
||||
Coder collects anonymized usage data
|
||||
to help improve our product.
|
||||
Consumes $CODER_TELEMETRY_ENABLE
|
||||
--telemetry-trace Whether Opentelemetry traces are
|
||||
sent to Coder. Coder collects
|
||||
anonymized application tracing to
|
||||
help improve our product. Disabling
|
||||
telemetry also disables this option.
|
||||
Consumes $CODER_TELEMETRY_TRACE
|
||||
--tls-address string HTTPS bind address of the server.
|
||||
Consumes $CODER_TLS_ADDRESS (default
|
||||
"127.0.0.1:3443")
|
||||
--tls-cert-file strings Path to each certificate for TLS. It
|
||||
requires a PEM-encoded file. To
|
||||
configure the listener to use a CA
|
||||
certificate, concatenate the primary
|
||||
certificate and the CA certificate
|
||||
together. The primary certificate
|
||||
should appear first in the combined
|
||||
file.
|
||||
Consumes $CODER_TLS_CERT_FILE
|
||||
--tls-client-auth string Policy the server will follow for
|
||||
TLS Client Authentication. Accepted
|
||||
values are "none", "request",
|
||||
"require-any", "verify-if-given", or
|
||||
"require-and-verify".
|
||||
Consumes $CODER_TLS_CLIENT_AUTH
|
||||
(default "none")
|
||||
--tls-client-ca-file string PEM-encoded Certificate Authority
|
||||
file used for checking the
|
||||
authenticity of client
|
||||
Consumes $CODER_TLS_CLIENT_CA_FILE
|
||||
--tls-client-cert-file string Path to certificate for client TLS
|
||||
authentication. It requires a
|
||||
PEM-encoded file.
|
||||
Consumes $CODER_TLS_CLIENT_CERT_FILE
|
||||
--tls-client-key-file string Path to key for client TLS
|
||||
authentication. It requires a
|
||||
PEM-encoded file.
|
||||
Consumes $CODER_TLS_CLIENT_KEY_FILE
|
||||
--tls-enable Whether TLS will be enabled.
|
||||
Consumes $CODER_TLS_ENABLE
|
||||
--tls-key-file strings Paths to the private keys for each
|
||||
of the certificates. It requires a
|
||||
PEM-encoded file.
|
||||
Consumes $CODER_TLS_KEY_FILE
|
||||
--tls-min-version string Minimum supported version of TLS.
|
||||
Accepted values are "tls10",
|
||||
"tls11", "tls12" or "tls13"
|
||||
Consumes $CODER_TLS_MIN_VERSION
|
||||
(default "tls12")
|
||||
--trace Whether application tracing data is
|
||||
collected. It exports to a backend
|
||||
configured by environment variables.
|
||||
See:
|
||||
https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md
|
||||
Consumes $CODER_TRACE_ENABLE
|
||||
--trace-honeycomb-api-key string Enables trace exporting to
|
||||
Honeycomb.io using the provided API
|
||||
Key.
|
||||
Consumes $CODER_TRACE_HONEYCOMB_API_KEY
|
||||
--trace-logs Enables capturing of logs as events
|
||||
in traces. This is useful for
|
||||
debugging, but may result in a very
|
||||
large amount of events being sent to
|
||||
the tracing backend which may incur
|
||||
significant costs. If the verbose
|
||||
flag was supplied, debug-level logs
|
||||
will be included.
|
||||
Consumes $CODER_TRACE_CAPTURE_LOGS
|
||||
--update-check Periodically check for new releases
|
||||
of Coder and inform the owner. The
|
||||
check is performed once per day.
|
||||
Consumes $CODER_UPDATE_CHECK
|
||||
--wildcard-access-url string Specifies the wildcard hostname to
|
||||
use for workspace applications in
|
||||
the form "*.example.com".
|
||||
Consumes $CODER_WILDCARD_ACCESS_URL
|
||||
|
||||
Global Flags:
|
||||
--global-config coder Path to the global coder config directory.
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
Create a new admin user with the given username, email and password and adds it to every organization.
|
||||
|
||||
Usage:
|
||||
coder server create-admin-user [flags]
|
||||
|
||||
Flags:
|
||||
--email string The email of the new user. If not specified, you will be
|
||||
prompted via stdin. Consumes $CODER_EMAIL.
|
||||
-h, --help help for create-admin-user
|
||||
--password string The password of the new user. If not specified, you will
|
||||
be prompted via stdin. Consumes $CODER_PASSWORD.
|
||||
--postgres-url string URL of a PostgreSQL database. If empty, the built-in
|
||||
PostgreSQL deployment will be used (Coder must not be
|
||||
already running in this case). Consumes $CODER_POSTGRES_URL.
|
||||
--ssh-keygen-algorithm string The algorithm to use for generating ssh keys. Accepted
|
||||
values are "ed25519", "ecdsa", or "rsa4096". Consumes
|
||||
$CODER_SSH_KEYGEN_ALGORITHM. (default "ed25519")
|
||||
--username string The username of the new user. If not specified, you will
|
||||
be prompted via stdin. Consumes $CODER_USERNAME.
|
||||
|
||||
Global Flags:
|
||||
--global-config coder Path to the global coder config directory.
|
||||
Consumes $CODER_CONFIG_DIR (default "~/.config/coderv2")
|
||||
--header stringArray HTTP headers added to all requests. Provide as "Key=Value".
|
||||
Consumes $CODER_HEADER
|
||||
--no-feature-warning Suppress warnings about unlicensed features.
|
||||
Consumes $CODER_NO_FEATURE_WARNING
|
||||
--no-version-warning Suppress warning when client and server versions do not match.
|
||||
Consumes $CODER_NO_VERSION_WARNING
|
||||
--token string Specify an authentication token. For security reasons setting
|
||||
CODER_SESSION_TOKEN is preferred.
|
||||
Consumes $CODER_SESSION_TOKEN
|
||||
--url string URL to a deployment.
|
||||
Consumes $CODER_URL
|
||||
-v, --verbose Enable verbose output.
|
||||
Consumes $CODER_VERBOSE
|
|
@ -6012,6 +6012,9 @@ const docTemplate = `{
|
|||
"derp": {
|
||||
"$ref": "#/definitions/codersdk.DERP"
|
||||
},
|
||||
"disable_password_auth": {
|
||||
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
|
||||
},
|
||||
"disable_path_apps": {
|
||||
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
|
||||
},
|
||||
|
|
|
@ -5343,6 +5343,9 @@
|
|||
"derp": {
|
||||
"$ref": "#/definitions/codersdk.DERP"
|
||||
},
|
||||
"disable_password_auth": {
|
||||
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
|
||||
},
|
||||
"disable_path_apps": {
|
||||
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
|
||||
},
|
||||
|
|
|
@ -18,15 +18,15 @@ import (
|
|||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
var validate *validator.Validate
|
||||
var Validate *validator.Validate
|
||||
|
||||
// This init is used to create a validator and register validation-specific
|
||||
// functionality for the HTTP API.
|
||||
//
|
||||
// A single validator instance is used, because it caches struct parsing.
|
||||
func init() {
|
||||
validate = validator.New()
|
||||
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
|
||||
Validate = validator.New()
|
||||
Validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
|
||||
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
|
||||
if name == "-" {
|
||||
return ""
|
||||
|
@ -44,7 +44,7 @@ func init() {
|
|||
return valid == nil
|
||||
}
|
||||
for _, tag := range []string{"username", "template_name", "workspace_name"} {
|
||||
err := validate.RegisterValidation(tag, nameValidator)
|
||||
err := Validate.RegisterValidation(tag, nameValidator)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func init() {
|
|||
valid := TemplateDisplayNameValid(str)
|
||||
return valid == nil
|
||||
}
|
||||
err := validate.RegisterValidation("template_display_name", templateDisplayNameValidator)
|
||||
err := Validate.RegisterValidation("template_display_name", templateDisplayNameValidator)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ func Read(ctx context.Context, rw http.ResponseWriter, r *http.Request, value in
|
|||
})
|
||||
return false
|
||||
}
|
||||
err = validate.Struct(value)
|
||||
err = Validate.Struct(value)
|
||||
var validationErrors validator.ValidationErrors
|
||||
if errors.As(err, &validationErrors) {
|
||||
apiErrors := make([]codersdk.ValidationError, 0, len(validationErrors))
|
||||
|
|
|
@ -62,8 +62,10 @@ func (api *API) userAuthMethods(rw http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.AuthMethods{
|
||||
Password: codersdk.AuthMethod{Enabled: true},
|
||||
Github: codersdk.AuthMethod{Enabled: api.GithubOAuth2Config != nil},
|
||||
Password: codersdk.AuthMethod{
|
||||
Enabled: !api.DeploymentConfig.DisablePasswordAuth.Value,
|
||||
},
|
||||
Github: codersdk.AuthMethod{Enabled: api.GithubOAuth2Config != nil},
|
||||
OIDC: codersdk.OIDCAuthMethod{
|
||||
AuthMethod: codersdk.AuthMethod{Enabled: api.OIDCConfig != nil},
|
||||
SignInText: signInText,
|
||||
|
|
|
@ -1028,6 +1028,24 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// If password authentication is disabled and the user does not have the
|
||||
// owner role, block the request.
|
||||
if api.DeploymentConfig.DisablePasswordAuth.Value {
|
||||
permitted := false
|
||||
for _, role := range user.RBACRoles {
|
||||
if role == rbac.RoleOwner() {
|
||||
permitted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !permitted {
|
||||
httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
|
||||
Message: "Password authentication is disabled. Only administrators can sign in with password authentication.",
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if user.LoginType != database.LoginTypePassword {
|
||||
httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
|
||||
Message: fmt.Sprintf("Incorrect login type, attempting to use %q but user is of login type %q", database.LoginTypePassword, user.LoginType),
|
||||
|
|
|
@ -86,35 +86,6 @@ func TestFirstUser(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
<-called
|
||||
})
|
||||
|
||||
t.Run("LastSeenAt", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
client := coderdtest.New(t, nil)
|
||||
firstUserResp := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
firstUser, err := client.User(ctx, firstUserResp.UserID.String())
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = coderdtest.CreateAnotherUser(t, client, firstUserResp.OrganizationID)
|
||||
|
||||
allUsersRes, err := client.Users(ctx, codersdk.UsersRequest{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, allUsersRes.Users, 2)
|
||||
|
||||
// We sent the "GET Users" request with the first user, but the second user
|
||||
// should be Never since they haven't performed a request.
|
||||
for _, user := range allUsersRes.Users {
|
||||
if user.ID == firstUser.ID {
|
||||
require.WithinDuration(t, firstUser.LastSeenAt, database.Now(), testutil.WaitShort)
|
||||
} else {
|
||||
require.Zero(t, user.LastSeenAt)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPostLogin(t *testing.T) {
|
||||
|
@ -191,6 +162,56 @@ func TestPostLogin(t *testing.T) {
|
|||
require.Contains(t, apiErr.Message, "suspended")
|
||||
})
|
||||
|
||||
t.Run("DisabledPasswordAuth", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dc := coderdtest.DeploymentConfig(t)
|
||||
dc.DisablePasswordAuth.Value = true
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
DeploymentConfig: dc,
|
||||
})
|
||||
|
||||
first := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
// With a user account.
|
||||
const password = "testpass"
|
||||
user, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
|
||||
Email: "test+user-@coder.com",
|
||||
Username: "user",
|
||||
Password: password,
|
||||
OrganizationID: first.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
userClient := codersdk.New(client.URL)
|
||||
_, err = userClient.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
|
||||
Email: user.Email,
|
||||
Password: password,
|
||||
})
|
||||
require.Error(t, err)
|
||||
var apiErr *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiErr)
|
||||
require.Equal(t, http.StatusForbidden, apiErr.StatusCode())
|
||||
require.Contains(t, apiErr.Message, "Password authentication is disabled")
|
||||
|
||||
// Promote the user account to an owner.
|
||||
_, err = client.UpdateUserRoles(ctx, user.ID.String(), codersdk.UpdateRoles{
|
||||
Roles: []string{rbac.RoleOwner(), rbac.RoleMember()},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Login with the user account.
|
||||
res, err := userClient.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
|
||||
Email: user.Email,
|
||||
Password: password,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, res.SessionToken)
|
||||
})
|
||||
|
||||
t.Run("Success", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
|
@ -437,6 +458,35 @@ func TestPostUsers(t *testing.T) {
|
|||
require.Len(t, auditor.AuditLogs, 1)
|
||||
assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs[0].Action)
|
||||
})
|
||||
|
||||
t.Run("LastSeenAt", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
client := coderdtest.New(t, nil)
|
||||
firstUserResp := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
firstUser, err := client.User(ctx, firstUserResp.UserID.String())
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = coderdtest.CreateAnotherUser(t, client, firstUserResp.OrganizationID)
|
||||
|
||||
allUsersRes, err := client.Users(ctx, codersdk.UsersRequest{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, allUsersRes.Users, 2)
|
||||
|
||||
// We sent the "GET Users" request with the first user, but the second user
|
||||
// should be Never since they haven't performed a request.
|
||||
for _, user := range allUsersRes.Users {
|
||||
if user.ID == firstUser.ID {
|
||||
require.WithinDuration(t, firstUser.LastSeenAt, database.Now(), testutil.WaitShort)
|
||||
} else {
|
||||
require.Zero(t, user.LastSeenAt)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateUserProfile(t *testing.T) {
|
||||
|
|
|
@ -144,6 +144,7 @@ type DeploymentConfig struct {
|
|||
DisablePathApps *DeploymentConfigField[bool] `json:"disable_path_apps" typescript:",notnull"`
|
||||
SessionDuration *DeploymentConfigField[time.Duration] `json:"max_session_expiry" typescript:",notnull"`
|
||||
DisableSessionExpiryRefresh *DeploymentConfigField[bool] `json:"disable_session_expiry_refresh" typescript:",notnull"`
|
||||
DisablePasswordAuth *DeploymentConfigField[bool] `json:"disable_password_auth" typescript:",notnull"`
|
||||
|
||||
// DEPRECATED: Use HTTPAddress or TLS.Address instead.
|
||||
Address *DeploymentConfigField[string] `json:"address" typescript:",notnull"`
|
||||
|
|
|
@ -289,6 +289,17 @@ curl -X GET http://coder-server:8080/api/v2/config/deployment \
|
|||
}
|
||||
}
|
||||
},
|
||||
"disable_password_auth": {
|
||||
"default": true,
|
||||
"enterprise": true,
|
||||
"flag": "string",
|
||||
"hidden": true,
|
||||
"name": "string",
|
||||
"secret": true,
|
||||
"shorthand": "string",
|
||||
"usage": "string",
|
||||
"value": true
|
||||
},
|
||||
"disable_path_apps": {
|
||||
"default": true,
|
||||
"enterprise": true,
|
||||
|
|
|
@ -1647,6 +1647,17 @@ CreateParameterRequest is a structure used to create a new parameter value for a
|
|||
}
|
||||
}
|
||||
},
|
||||
"disable_password_auth": {
|
||||
"default": true,
|
||||
"enterprise": true,
|
||||
"flag": "string",
|
||||
"hidden": true,
|
||||
"name": "string",
|
||||
"secret": true,
|
||||
"shorthand": "string",
|
||||
"usage": "string",
|
||||
"value": true
|
||||
},
|
||||
"disable_path_apps": {
|
||||
"default": true,
|
||||
"enterprise": true,
|
||||
|
@ -2438,6 +2449,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
|
|||
| `cache_directory` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | |
|
||||
| `dangerous` | [codersdk.DangerousConfig](#codersdkdangerousconfig) | false | | |
|
||||
| `derp` | [codersdk.DERP](#codersdkderp) | false | | |
|
||||
| `disable_password_auth` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | |
|
||||
| `disable_path_apps` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | |
|
||||
| `disable_session_expiry_refresh` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | |
|
||||
| `experimental` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | Experimental Use Experiments instead. |
|
||||
|
|
|
@ -9,147 +9,149 @@ coder server [flags]
|
|||
### Options
|
||||
|
||||
```
|
||||
--access-url string External URL to access your deployment. This must be accessible by all provisioned workspaces.
|
||||
Consumes $CODER_ACCESS_URL
|
||||
--api-rate-limit int Maximum number of requests per minute allowed to the API per user, or per IP address for unauthenticated users. Negative values mean no rate limit. Some API endpoints have separate strict rate limits regardless of this value to prevent denial-of-service or brute force attacks.
|
||||
Consumes $CODER_API_RATE_LIMIT (default 512)
|
||||
--cache-dir string The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.
|
||||
Consumes $CODER_CACHE_DIRECTORY (default "~/.cache/coder")
|
||||
--dangerous-allow-path-app-sharing Allow workspace apps that are not served from subdomains to be shared. Path-based app sharing is DISABLED by default for security purposes. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.
|
||||
Consumes $CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
|
||||
--dangerous-allow-path-app-site-owner-access Allow site-owners to access workspace apps from workspaces they do not own. Owners cannot access path-based apps they do not own by default. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.
|
||||
Consumes $CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
|
||||
--dangerous-disable-rate-limits Disables all rate limits. This is not recommended in production.
|
||||
Consumes $CODER_RATE_LIMIT_DISABLE_ALL
|
||||
--derp-config-path string Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/
|
||||
Consumes $CODER_DERP_CONFIG_PATH
|
||||
--derp-config-url string URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/
|
||||
Consumes $CODER_DERP_CONFIG_URL
|
||||
--derp-server-enable Whether to enable or disable the embedded DERP relay server.
|
||||
Consumes $CODER_DERP_SERVER_ENABLE (default true)
|
||||
--derp-server-region-code string Region code to use for the embedded DERP server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_CODE (default "coder")
|
||||
--derp-server-region-id int Region ID to use for the embedded DERP server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_ID (default 999)
|
||||
--derp-server-region-name string Region name that for the embedded DERP server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_NAME (default "Coder Embedded Relay")
|
||||
--derp-server-stun-addresses strings Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.
|
||||
Consumes $CODER_DERP_SERVER_STUN_ADDRESSES (default [stun.l.google.com:19302])
|
||||
--disable-path-apps Disable workspace apps that are not served from subdomains. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. This is recommended for security purposes if a --wildcard-access-url is configured.
|
||||
Consumes $CODER_DISABLE_PATH_APPS
|
||||
--disable-session-expiry-refresh Disable automatic session expiry bumping due to activity. This forces all sessions to become invalid after the session expiry duration has been reached.
|
||||
Consumes $CODER_DISABLE_SESSION_EXPIRY_REFRESH
|
||||
--experiments strings Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.
|
||||
Consumes $CODER_EXPERIMENTS
|
||||
-h, --help help for server
|
||||
--http-address string HTTP bind address of the server. Unset to disable the HTTP endpoint.
|
||||
Consumes $CODER_HTTP_ADDRESS (default "127.0.0.1:3000")
|
||||
--log-human string Output human-readable logs to a given file.
|
||||
Consumes $CODER_LOGGING_HUMAN (default "/dev/stderr")
|
||||
--log-json string Output JSON logs to a given file.
|
||||
Consumes $CODER_LOGGING_JSON
|
||||
--log-stackdriver string Output Stackdriver compatible logs to a given file.
|
||||
Consumes $CODER_LOGGING_STACKDRIVER
|
||||
--max-token-lifetime duration The maximum lifetime duration users can specify when creating an API token.
|
||||
Consumes $CODER_MAX_TOKEN_LIFETIME (default 720h0m0s)
|
||||
--oauth2-github-allow-everyone Allow all logins, setting this option means allowed orgs and teams must be empty.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
|
||||
--oauth2-github-allow-signups Whether new users can sign up with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
|
||||
--oauth2-github-allowed-orgs strings Organizations the user must be a member of to Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_ORGS
|
||||
--oauth2-github-allowed-teams strings Teams inside organizations the user must be a member of to Login with GitHub. Structured as: <organization-name>/<team-slug>.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_TEAMS
|
||||
--oauth2-github-client-id string Client ID for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_CLIENT_ID
|
||||
--oauth2-github-client-secret string Client secret for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_CLIENT_SECRET
|
||||
--oauth2-github-enterprise-base-url string Base URL of a GitHub Enterprise deployment to use for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL
|
||||
--oidc-allow-signups Whether new users can sign up with OIDC.
|
||||
Consumes $CODER_OIDC_ALLOW_SIGNUPS (default true)
|
||||
--oidc-client-id string Client ID to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_CLIENT_ID
|
||||
--oidc-client-secret string Client secret to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_CLIENT_SECRET
|
||||
--oidc-email-domain strings Email domains that clients logging in with OIDC must match.
|
||||
Consumes $CODER_OIDC_EMAIL_DOMAIN
|
||||
--oidc-icon-url string URL pointing to the icon to use on the OepnID Connect login button
|
||||
Consumes $CODER_OIDC_ICON_URL
|
||||
--oidc-ignore-email-verified Ignore the email_verified claim from the upstream provider.
|
||||
Consumes $CODER_OIDC_IGNORE_EMAIL_VERIFIED
|
||||
--oidc-issuer-url string Issuer URL to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_ISSUER_URL
|
||||
--oidc-scopes strings Scopes to grant when authenticating with OIDC.
|
||||
Consumes $CODER_OIDC_SCOPES (default [openid,profile,email])
|
||||
--oidc-sign-in-text string The text to show on the OpenID Connect sign in button
|
||||
Consumes $CODER_OIDC_SIGN_IN_TEXT (default "OpenID Connect")
|
||||
--oidc-username-field string OIDC claim field to use as the username.
|
||||
Consumes $CODER_OIDC_USERNAME_FIELD (default "preferred_username")
|
||||
--postgres-url string URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with "coder server postgres-builtin-url".
|
||||
Consumes $CODER_PG_CONNECTION_URL
|
||||
--pprof-address string The bind address to serve pprof.
|
||||
Consumes $CODER_PPROF_ADDRESS (default "127.0.0.1:6060")
|
||||
--pprof-enable Serve pprof metrics on the address defined by pprof address.
|
||||
Consumes $CODER_PPROF_ENABLE
|
||||
--prometheus-address string The bind address to serve prometheus metrics.
|
||||
Consumes $CODER_PROMETHEUS_ADDRESS (default "127.0.0.1:2112")
|
||||
--prometheus-enable Serve prometheus metrics on the address defined by prometheus address.
|
||||
Consumes $CODER_PROMETHEUS_ENABLE
|
||||
--provisioner-daemon-poll-interval duration Time to wait before polling for a new job.
|
||||
Consumes $CODER_PROVISIONER_DAEMON_POLL_INTERVAL (default 1s)
|
||||
--provisioner-daemon-poll-jitter duration Random jitter added to the poll interval.
|
||||
Consumes $CODER_PROVISIONER_DAEMON_POLL_JITTER (default 100ms)
|
||||
--provisioner-daemons int Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.
|
||||
Consumes $CODER_PROVISIONER_DAEMONS (default 3)
|
||||
--provisioner-force-cancel-interval duration Time to force cancel provisioning tasks that are stuck.
|
||||
Consumes $CODER_PROVISIONER_FORCE_CANCEL_INTERVAL (default 10m0s)
|
||||
--proxy-trusted-headers strings Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-Ip, True-Client-Ip, X-Forwarded-For
|
||||
Consumes $CODER_PROXY_TRUSTED_HEADERS
|
||||
--proxy-trusted-origins strings Origin addresses to respect "proxy-trusted-headers". e.g. 192.168.1.0/24
|
||||
Consumes $CODER_PROXY_TRUSTED_ORIGINS
|
||||
--redirect-to-access-url Specifies whether to redirect requests that do not match the access URL host.
|
||||
Consumes $CODER_REDIRECT_TO_ACCESS_URL
|
||||
--secure-auth-cookie Controls if the 'Secure' property is set on browser session cookies.
|
||||
Consumes $CODER_SECURE_AUTH_COOKIE
|
||||
--session-duration duration The token expiry duration for browser sessions. Sessions may last longer if they are actively making requests, but this functionality can be disabled via --disable-session-expiry-refresh.
|
||||
Consumes $CODER_MAX_SESSION_EXPIRY (default 24h0m0s)
|
||||
--ssh-keygen-algorithm string The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096".
|
||||
Consumes $CODER_SSH_KEYGEN_ALGORITHM (default "ed25519")
|
||||
--swagger-enable Expose the swagger endpoint via /swagger.
|
||||
Consumes $CODER_SWAGGER_ENABLE
|
||||
--telemetry Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.
|
||||
Consumes $CODER_TELEMETRY_ENABLE (default true)
|
||||
--telemetry-trace Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.
|
||||
Consumes $CODER_TELEMETRY_TRACE (default true)
|
||||
--tls-address string HTTPS bind address of the server.
|
||||
Consumes $CODER_TLS_ADDRESS (default "127.0.0.1:3443")
|
||||
--tls-cert-file strings Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.
|
||||
Consumes $CODER_TLS_CERT_FILE
|
||||
--tls-client-auth string Policy the server will follow for TLS Client Authentication. Accepted values are "none", "request", "require-any", "verify-if-given", or "require-and-verify".
|
||||
Consumes $CODER_TLS_CLIENT_AUTH (default "none")
|
||||
--tls-client-ca-file string PEM-encoded Certificate Authority file used for checking the authenticity of client
|
||||
Consumes $CODER_TLS_CLIENT_CA_FILE
|
||||
--tls-client-cert-file string Path to certificate for client TLS authentication. It requires a PEM-encoded file.
|
||||
Consumes $CODER_TLS_CLIENT_CERT_FILE
|
||||
--tls-client-key-file string Path to key for client TLS authentication. It requires a PEM-encoded file.
|
||||
Consumes $CODER_TLS_CLIENT_KEY_FILE
|
||||
--tls-enable Whether TLS will be enabled.
|
||||
Consumes $CODER_TLS_ENABLE
|
||||
--tls-key-file strings Paths to the private keys for each of the certificates. It requires a PEM-encoded file.
|
||||
Consumes $CODER_TLS_KEY_FILE
|
||||
--tls-min-version string Minimum supported version of TLS. Accepted values are "tls10", "tls11", "tls12" or "tls13"
|
||||
Consumes $CODER_TLS_MIN_VERSION (default "tls12")
|
||||
--trace Whether application tracing data is collected. It exports to a backend configured by environment variables. See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md
|
||||
Consumes $CODER_TRACE_ENABLE
|
||||
--trace-honeycomb-api-key string Enables trace exporting to Honeycomb.io using the provided API Key.
|
||||
Consumes $CODER_TRACE_HONEYCOMB_API_KEY
|
||||
--trace-logs Enables capturing of logs as events in traces. This is useful for debugging, but may result in a very large amount of events being sent to the tracing backend which may incur significant costs. If the verbose flag was supplied, debug-level logs will be included.
|
||||
Consumes $CODER_TRACE_CAPTURE_LOGS
|
||||
--update-check Periodically check for new releases of Coder and inform the owner. The check is performed once per day.
|
||||
Consumes $CODER_UPDATE_CHECK
|
||||
--wildcard-access-url string Specifies the wildcard hostname to use for workspace applications in the form "*.example.com".
|
||||
Consumes $CODER_WILDCARD_ACCESS_URL
|
||||
--access-url string External URL to access your deployment. This must be accessible by all provisioned workspaces.
|
||||
Consumes $CODER_ACCESS_URL
|
||||
--api-rate-limit int Maximum number of requests per minute allowed to the API per user, or per IP address for unauthenticated users. Negative values mean no rate limit. Some API endpoints have separate strict rate limits regardless of this value to prevent denial-of-service or brute force attacks.
|
||||
Consumes $CODER_API_RATE_LIMIT (default 512)
|
||||
--cache-dir string The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.
|
||||
Consumes $CODER_CACHE_DIRECTORY (default "~/.cache/coder")
|
||||
--dangerous-allow-path-app-sharing Allow workspace apps that are not served from subdomains to be shared. Path-based app sharing is DISABLED by default for security purposes. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.
|
||||
Consumes $CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
|
||||
--dangerous-allow-path-app-site-owner-access Allow site-owners to access workspace apps from workspaces they do not own. Owners cannot access path-based apps they do not own by default. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.
|
||||
Consumes $CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
|
||||
--dangerous-disable-rate-limits Disables all rate limits. This is not recommended in production.
|
||||
Consumes $CODER_RATE_LIMIT_DISABLE_ALL
|
||||
--derp-config-path string Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/
|
||||
Consumes $CODER_DERP_CONFIG_PATH
|
||||
--derp-config-url string URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/
|
||||
Consumes $CODER_DERP_CONFIG_URL
|
||||
--derp-server-enable Whether to enable or disable the embedded DERP relay server.
|
||||
Consumes $CODER_DERP_SERVER_ENABLE (default true)
|
||||
--derp-server-region-code string Region code to use for the embedded DERP server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_CODE (default "coder")
|
||||
--derp-server-region-id int Region ID to use for the embedded DERP server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_ID (default 999)
|
||||
--derp-server-region-name string Region name that for the embedded DERP server.
|
||||
Consumes $CODER_DERP_SERVER_REGION_NAME (default "Coder Embedded Relay")
|
||||
--derp-server-stun-addresses strings Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.
|
||||
Consumes $CODER_DERP_SERVER_STUN_ADDRESSES (default [stun.l.google.com:19302])
|
||||
--disable-password-auth coder server create-admin Disable password authentication. This is recommended for security purposes in production deployments that rely on an identity provider. Any user with the owner role will be able to sign in with their password regardless of this setting to avoid potential lock out. If you are locked out of your account, you can use the coder server create-admin command to create a new admin user directly in the database.
|
||||
Consumes $CODER_DISABLE_PASSWORD_AUTH
|
||||
--disable-path-apps Disable workspace apps that are not served from subdomains. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. This is recommended for security purposes if a --wildcard-access-url is configured.
|
||||
Consumes $CODER_DISABLE_PATH_APPS
|
||||
--disable-session-expiry-refresh Disable automatic session expiry bumping due to activity. This forces all sessions to become invalid after the session expiry duration has been reached.
|
||||
Consumes $CODER_DISABLE_SESSION_EXPIRY_REFRESH
|
||||
--experiments strings Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.
|
||||
Consumes $CODER_EXPERIMENTS
|
||||
-h, --help help for server
|
||||
--http-address string HTTP bind address of the server. Unset to disable the HTTP endpoint.
|
||||
Consumes $CODER_HTTP_ADDRESS (default "127.0.0.1:3000")
|
||||
--log-human string Output human-readable logs to a given file.
|
||||
Consumes $CODER_LOGGING_HUMAN (default "/dev/stderr")
|
||||
--log-json string Output JSON logs to a given file.
|
||||
Consumes $CODER_LOGGING_JSON
|
||||
--log-stackdriver string Output Stackdriver compatible logs to a given file.
|
||||
Consumes $CODER_LOGGING_STACKDRIVER
|
||||
--max-token-lifetime duration The maximum lifetime duration users can specify when creating an API token.
|
||||
Consumes $CODER_MAX_TOKEN_LIFETIME (default 720h0m0s)
|
||||
--oauth2-github-allow-everyone Allow all logins, setting this option means allowed orgs and teams must be empty.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
|
||||
--oauth2-github-allow-signups Whether new users can sign up with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
|
||||
--oauth2-github-allowed-orgs strings Organizations the user must be a member of to Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_ORGS
|
||||
--oauth2-github-allowed-teams strings Teams inside organizations the user must be a member of to Login with GitHub. Structured as: <organization-name>/<team-slug>.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_TEAMS
|
||||
--oauth2-github-client-id string Client ID for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_CLIENT_ID
|
||||
--oauth2-github-client-secret string Client secret for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_CLIENT_SECRET
|
||||
--oauth2-github-enterprise-base-url string Base URL of a GitHub Enterprise deployment to use for Login with GitHub.
|
||||
Consumes $CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL
|
||||
--oidc-allow-signups Whether new users can sign up with OIDC.
|
||||
Consumes $CODER_OIDC_ALLOW_SIGNUPS (default true)
|
||||
--oidc-client-id string Client ID to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_CLIENT_ID
|
||||
--oidc-client-secret string Client secret to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_CLIENT_SECRET
|
||||
--oidc-email-domain strings Email domains that clients logging in with OIDC must match.
|
||||
Consumes $CODER_OIDC_EMAIL_DOMAIN
|
||||
--oidc-icon-url string URL pointing to the icon to use on the OepnID Connect login button
|
||||
Consumes $CODER_OIDC_ICON_URL
|
||||
--oidc-ignore-email-verified Ignore the email_verified claim from the upstream provider.
|
||||
Consumes $CODER_OIDC_IGNORE_EMAIL_VERIFIED
|
||||
--oidc-issuer-url string Issuer URL to use for Login with OIDC.
|
||||
Consumes $CODER_OIDC_ISSUER_URL
|
||||
--oidc-scopes strings Scopes to grant when authenticating with OIDC.
|
||||
Consumes $CODER_OIDC_SCOPES (default [openid,profile,email])
|
||||
--oidc-sign-in-text string The text to show on the OpenID Connect sign in button
|
||||
Consumes $CODER_OIDC_SIGN_IN_TEXT (default "OpenID Connect")
|
||||
--oidc-username-field string OIDC claim field to use as the username.
|
||||
Consumes $CODER_OIDC_USERNAME_FIELD (default "preferred_username")
|
||||
--postgres-url string URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with "coder server postgres-builtin-url".
|
||||
Consumes $CODER_PG_CONNECTION_URL
|
||||
--pprof-address string The bind address to serve pprof.
|
||||
Consumes $CODER_PPROF_ADDRESS (default "127.0.0.1:6060")
|
||||
--pprof-enable Serve pprof metrics on the address defined by pprof address.
|
||||
Consumes $CODER_PPROF_ENABLE
|
||||
--prometheus-address string The bind address to serve prometheus metrics.
|
||||
Consumes $CODER_PROMETHEUS_ADDRESS (default "127.0.0.1:2112")
|
||||
--prometheus-enable Serve prometheus metrics on the address defined by prometheus address.
|
||||
Consumes $CODER_PROMETHEUS_ENABLE
|
||||
--provisioner-daemon-poll-interval duration Time to wait before polling for a new job.
|
||||
Consumes $CODER_PROVISIONER_DAEMON_POLL_INTERVAL (default 1s)
|
||||
--provisioner-daemon-poll-jitter duration Random jitter added to the poll interval.
|
||||
Consumes $CODER_PROVISIONER_DAEMON_POLL_JITTER (default 100ms)
|
||||
--provisioner-daemons int Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.
|
||||
Consumes $CODER_PROVISIONER_DAEMONS (default 3)
|
||||
--provisioner-force-cancel-interval duration Time to force cancel provisioning tasks that are stuck.
|
||||
Consumes $CODER_PROVISIONER_FORCE_CANCEL_INTERVAL (default 10m0s)
|
||||
--proxy-trusted-headers strings Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-Ip, True-Client-Ip, X-Forwarded-For
|
||||
Consumes $CODER_PROXY_TRUSTED_HEADERS
|
||||
--proxy-trusted-origins strings Origin addresses to respect "proxy-trusted-headers". e.g. 192.168.1.0/24
|
||||
Consumes $CODER_PROXY_TRUSTED_ORIGINS
|
||||
--redirect-to-access-url Specifies whether to redirect requests that do not match the access URL host.
|
||||
Consumes $CODER_REDIRECT_TO_ACCESS_URL
|
||||
--secure-auth-cookie Controls if the 'Secure' property is set on browser session cookies.
|
||||
Consumes $CODER_SECURE_AUTH_COOKIE
|
||||
--session-duration duration The token expiry duration for browser sessions. Sessions may last longer if they are actively making requests, but this functionality can be disabled via --disable-session-expiry-refresh.
|
||||
Consumes $CODER_MAX_SESSION_EXPIRY (default 24h0m0s)
|
||||
--ssh-keygen-algorithm string The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096".
|
||||
Consumes $CODER_SSH_KEYGEN_ALGORITHM (default "ed25519")
|
||||
--swagger-enable Expose the swagger endpoint via /swagger.
|
||||
Consumes $CODER_SWAGGER_ENABLE
|
||||
--telemetry Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.
|
||||
Consumes $CODER_TELEMETRY_ENABLE (default true)
|
||||
--telemetry-trace Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.
|
||||
Consumes $CODER_TELEMETRY_TRACE (default true)
|
||||
--tls-address string HTTPS bind address of the server.
|
||||
Consumes $CODER_TLS_ADDRESS (default "127.0.0.1:3443")
|
||||
--tls-cert-file strings Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.
|
||||
Consumes $CODER_TLS_CERT_FILE
|
||||
--tls-client-auth string Policy the server will follow for TLS Client Authentication. Accepted values are "none", "request", "require-any", "verify-if-given", or "require-and-verify".
|
||||
Consumes $CODER_TLS_CLIENT_AUTH (default "none")
|
||||
--tls-client-ca-file string PEM-encoded Certificate Authority file used for checking the authenticity of client
|
||||
Consumes $CODER_TLS_CLIENT_CA_FILE
|
||||
--tls-client-cert-file string Path to certificate for client TLS authentication. It requires a PEM-encoded file.
|
||||
Consumes $CODER_TLS_CLIENT_CERT_FILE
|
||||
--tls-client-key-file string Path to key for client TLS authentication. It requires a PEM-encoded file.
|
||||
Consumes $CODER_TLS_CLIENT_KEY_FILE
|
||||
--tls-enable Whether TLS will be enabled.
|
||||
Consumes $CODER_TLS_ENABLE
|
||||
--tls-key-file strings Paths to the private keys for each of the certificates. It requires a PEM-encoded file.
|
||||
Consumes $CODER_TLS_KEY_FILE
|
||||
--tls-min-version string Minimum supported version of TLS. Accepted values are "tls10", "tls11", "tls12" or "tls13"
|
||||
Consumes $CODER_TLS_MIN_VERSION (default "tls12")
|
||||
--trace Whether application tracing data is collected. It exports to a backend configured by environment variables. See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md
|
||||
Consumes $CODER_TRACE_ENABLE
|
||||
--trace-honeycomb-api-key string Enables trace exporting to Honeycomb.io using the provided API Key.
|
||||
Consumes $CODER_TRACE_HONEYCOMB_API_KEY
|
||||
--trace-logs Enables capturing of logs as events in traces. This is useful for debugging, but may result in a very large amount of events being sent to the tracing backend which may incur significant costs. If the verbose flag was supplied, debug-level logs will be included.
|
||||
Consumes $CODER_TRACE_CAPTURE_LOGS
|
||||
--update-check Periodically check for new releases of Coder and inform the owner. The check is performed once per day.
|
||||
Consumes $CODER_UPDATE_CHECK
|
||||
--wildcard-access-url string Specifies the wildcard hostname to use for workspace applications in the form "*.example.com".
|
||||
Consumes $CODER_WILDCARD_ACCESS_URL
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
@ -174,5 +176,6 @@ coder server [flags]
|
|||
### SEE ALSO
|
||||
|
||||
- [coder](coder.md) -
|
||||
- [coder server create-admin-user](coder_server_create-admin-user.md) - Create a new admin user with the given username, email and password and adds it to every organization.
|
||||
- [coder server postgres-builtin-serve](coder_server_postgres-builtin-serve.md) - Run the built-in PostgreSQL deployment.
|
||||
- [coder server postgres-builtin-url](coder_server_postgres-builtin-url.md) - Output the connection URL for the built-in PostgreSQL deployment.
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
## coder server create-admin-user
|
||||
|
||||
Create a new admin user with the given username, email and password and adds it to every organization.
|
||||
|
||||
```
|
||||
coder server create-admin-user [flags]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--email string The email of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_EMAIL.
|
||||
-h, --help help for create-admin-user
|
||||
--password string The password of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_PASSWORD.
|
||||
--postgres-url string URL of a PostgreSQL database. If empty, the built-in PostgreSQL deployment will be used (Coder must not be already running in this case). Consumes $CODER_POSTGRES_URL.
|
||||
--ssh-keygen-algorithm string The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096". Consumes $CODER_SSH_KEYGEN_ALGORITHM. (default "ed25519")
|
||||
--username string The username of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_USERNAME.
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--global-config coder Path to the global coder config directory.
|
||||
Consumes $CODER_CONFIG_DIR (default "~/.config/coderv2")
|
||||
--header stringArray HTTP headers added to all requests. Provide as "Key=Value".
|
||||
Consumes $CODER_HEADER
|
||||
--no-feature-warning Suppress warnings about unlicensed features.
|
||||
Consumes $CODER_NO_FEATURE_WARNING
|
||||
--no-version-warning Suppress warning when client and server versions do not match.
|
||||
Consumes $CODER_NO_VERSION_WARNING
|
||||
--token string Specify an authentication token. For security reasons setting CODER_SESSION_TOKEN is preferred.
|
||||
Consumes $CODER_SESSION_TOKEN
|
||||
--url string URL to a deployment.
|
||||
Consumes $CODER_URL
|
||||
-v, --verbose Enable verbose output.
|
||||
Consumes $CODER_VERBOSE
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
- [coder server](coder_server.md) - Start a Coder server
|
|
@ -509,6 +509,10 @@
|
|||
"title": "server",
|
||||
"path": "./cli/coder_server.md"
|
||||
},
|
||||
{
|
||||
"title": "server create-admin-user",
|
||||
"path": "./cli/coder_server_create-admin-user.md"
|
||||
},
|
||||
{
|
||||
"title": "server postgres-builtin-serve",
|
||||
"path": "./cli/coder_server_postgres-builtin-serve.md"
|
||||
|
|
|
@ -327,6 +327,7 @@ export interface DeploymentConfig {
|
|||
readonly disable_path_apps: DeploymentConfigField<boolean>
|
||||
readonly max_session_expiry: DeploymentConfigField<number>
|
||||
readonly disable_session_expiry_refresh: DeploymentConfigField<boolean>
|
||||
readonly disable_password_auth: DeploymentConfigField<boolean>
|
||||
readonly address: DeploymentConfigField<string>
|
||||
readonly experimental: DeploymentConfigField<boolean>
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue