Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: Generate random admin user password in dev mode#1207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 34 additions & 19 deletionscli/server.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,27 +41,23 @@ import (
"github.com/coder/coder/coderd/gitsshkey"
"github.com/coder/coder/coderd/turnconn"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand"
"github.com/coder/coder/provisioner/terraform"
"github.com/coder/coder/provisionerd"
"github.com/coder/coder/provisionersdk"
"github.com/coder/coder/provisionersdk/proto"
)

var defaultDevUser = codersdk.CreateFirstUserRequest{
Email: "admin@coder.com",
Username: "developer",
Password: "password",
OrganizationName: "acme-corp",
}

// nolint:gocyclo
func server() *cobra.Command {
var (
accessURL string
address string
cacheDir string
dev bool
postgresURL string
accessURL string
address string
cacheDir string
dev bool
devUserEmail string
devUserPassword string
postgresURL string
// provisionerDaemonCount is a uint8 to ensure a number > 0.
provisionerDaemonCount uint8
oauth2GithubClientID string
Expand DownExpand Up@@ -278,12 +274,18 @@ func server() *cobra.Command {
config := createConfig(cmd)

if dev {
err = createFirstUser(cmd, client, config)
if devUserPassword == "" {
devUserPassword, err = cryptorand.String(10)
if err != nil {
return xerrors.Errorf("generate random admin password for dev: %w", err)
}
}
err = createFirstUser(cmd, client, config, devUserEmail, devUserPassword)
if err != nil {
return xerrors.Errorf("create first user: %w", err)
}
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "email: %s\n",defaultDevUser.Email)
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "password: %s\n",defaultDevUser.Password)
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "email: %s\n",devUserEmail)
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "password: %s\n",devUserPassword)
_, _ = fmt.Fprintln(cmd.ErrOrStderr())

_, _ = fmt.Fprintf(cmd.ErrOrStderr(), cliui.Styles.Wrap.Render(`Started in dev mode. All data is in-memory! `+cliui.Styles.Bold.Render("Do not use in production")+`. Press `+
Expand DownExpand Up@@ -409,6 +411,8 @@ func server() *cobra.Command {
// systemd uses the CACHE_DIRECTORY environment variable!
cliflag.StringVarP(root.Flags(), &cacheDir, "cache-dir", "", "CACHE_DIRECTORY", filepath.Join(os.TempDir(), "coder-cache"), "Specifies a directory to cache binaries for provision operations.")
cliflag.BoolVarP(root.Flags(), &dev, "dev", "", "CODER_DEV_MODE", false, "Serve Coder in dev mode for tinkering")
cliflag.StringVarP(root.Flags(), &devUserEmail, "dev-admin-email", "", "CODER_DEV_ADMIN_EMAIL", "admin@coder.com", "Specifies the admin email to be used in dev mode (--dev)")
cliflag.StringVarP(root.Flags(), &devUserPassword, "dev-admin-password", "", "CODER_DEV_ADMIN_PASSWORD", "", "Specifies the admin password to be used in dev mode (--dev) instead of a randomly generated one")
cliflag.StringVarP(root.Flags(), &postgresURL, "postgres-url", "", "CODER_PG_CONNECTION_URL", "", "URL of a PostgreSQL database to connect to")
cliflag.Uint8VarP(root.Flags(), &provisionerDaemonCount, "provisioner-daemons", "", "CODER_PROVISIONER_DAEMONS", 3, "The amount of provisioner daemons to create on start.")
cliflag.StringVarP(root.Flags(), &oauth2GithubClientID, "oauth2-github-client-id", "", "CODER_OAUTH2_GITHUB_CLIENT_ID", "",
Expand DownExpand Up@@ -450,14 +454,25 @@ func server() *cobra.Command {
return root
}

func createFirstUser(cmd *cobra.Command, client *codersdk.Client, cfg config.Root) error {
_, err := client.CreateFirstUser(cmd.Context(), defaultDevUser)
func createFirstUser(cmd *cobra.Command, client *codersdk.Client, cfg config.Root, email, password string) error {
if email == "" {
return xerrors.New("email is empty")
}
if password == "" {
return xerrors.New("password is empty")
}
_, err := client.CreateFirstUser(cmd.Context(), codersdk.CreateFirstUserRequest{
Email: email,
Username: "developer",
Password: password,
OrganizationName: "acme-corp",
})
if err != nil {
return xerrors.Errorf("create first user: %w", err)
}
token, err := client.LoginWithPassword(cmd.Context(), codersdk.LoginWithPasswordRequest{
Email:defaultDevUser.Email,
Password:defaultDevUser.Password,
Email:email,
Password:password,
})
if err != nil {
return xerrors.Errorf("login with first user: %w", err)
Expand Down
77 changes: 70 additions & 7 deletionscli/server_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
package cli_test

import (
"bytes"
"context"
"crypto/ecdsa"
"crypto/elliptic"
Expand All@@ -10,12 +9,15 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
"net/http"
"net/url"
"os"
"runtime"
"strings"
"sync"
"testing"
"time"

Expand DownExpand Up@@ -74,18 +76,30 @@ func TestServer(t *testing.T) {
t.Parallel()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()

wantEmail := "admin@coder.com"

root, cfg := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0")
var stdoutBuf bytes.Buffer
root.SetOutput(&stdoutBuf)
var buf strings.Builder
root.SetOutput(&buf)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()

err := root.ExecuteContext(ctx)
require.ErrorIs(t, err, context.Canceled)

// Verify that credentials were output to the terminal.
wantEmail := "email: admin@coder.com"
wantPassword := "password: password"
assert.Contains(t, stdoutBuf.String(), wantEmail, "expected output %q; got no match", wantEmail)
assert.Contains(t, stdoutBuf.String(), wantPassword, "expected output %q; got no match", wantPassword)
assert.Contains(t, buf.String(), fmt.Sprintf("email: %s", wantEmail), "expected output %q; got no match", wantEmail)
// Check that the password line is output and that it's non-empty.
if _, after, found := strings.Cut(buf.String(), "password: "); found {
before, _, _ := strings.Cut(after, "\n")
before = strings.Trim(before, "\r") // Ensure no control character is left.
assert.NotEmpty(t, before, "expected non-empty password; got empty")
} else {
t.Error("expected password line output; got no match")
}
}()
var token string
require.Eventually(t, func() bool {
Expand All@@ -102,6 +116,55 @@ func TestServer(t *testing.T) {
client.SessionToken = token
_, err = client.User(ctx, codersdk.Me)
require.NoError(t, err)

cancelFunc()
wg.Wait()
})
// Duplicated test from "Development" above to test setting email/password via env.
// Cannot run parallel due to os.Setenv.
//nolint:paralleltest
t.Run("Development with email and password from env", func(t *testing.T) {
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()

wantEmail := "myadmin@coder.com"
wantPassword := "testpass42"
t.Setenv("CODER_DEV_ADMIN_EMAIL", wantEmail)
t.Setenv("CODER_DEV_ADMIN_PASSWORD", wantPassword)

root, cfg := clitest.New(t, "server", "--dev", "--skip-tunnel", "--address", ":0")
var buf strings.Builder
root.SetOutput(&buf)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()

err := root.ExecuteContext(ctx)
require.ErrorIs(t, err, context.Canceled)

// Verify that credentials were output to the terminal.
assert.Contains(t, buf.String(), fmt.Sprintf("email: %s", wantEmail), "expected output %q; got no match", wantEmail)
assert.Contains(t, buf.String(), fmt.Sprintf("password: %s", wantPassword), "expected output %q; got no match", wantPassword)
}()
var token string
require.Eventually(t, func() bool {
var err error
token, err = cfg.Session().Read()
return err == nil
}, 15*time.Second, 25*time.Millisecond)
// Verify that authentication was properly set in dev-mode.
accessURL, err := cfg.URL().Read()
require.NoError(t, err)
parsed, err := url.Parse(accessURL)
require.NoError(t, err)
client := codersdk.New(parsed)
client.SessionToken = token
_, err = client.User(ctx, codersdk.Me)
require.NoError(t, err)

cancelFunc()
wg.Wait()
})
t.Run("TLSBadVersion", func(t *testing.T) {
t.Parallel()
Expand Down
6 changes: 5 additions & 1 deletionsite/e2e/playwright.config.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
import { PlaywrightTestConfig } from "@playwright/test"
import * as path from "path"
import * as constants from "./constants"

const config: PlaywrightTestConfig = {
testDir: "tests",
Expand All@@ -17,7 +18,10 @@ const config: PlaywrightTestConfig = {
// https://playwright.dev/docs/test-advanced#launching-a-development-web-server-during-the-tests
webServer: {
// Run the coder daemon directly.
command: `go run -tags embed ${path.join(__dirname, "../../cmd/coder/main.go")} server --dev --skip-tunnel`,
command: `go run -tags embed ${path.join(
__dirname,
"../../cmd/coder/main.go",
)} server --dev --skip-tunnel --dev-admin-email ${constants.email} --dev-admin-password ${constants.password}`,
port: 3000,
timeout: 120 * 10000,
reuseExistingServer: false,
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp