Skip to content

Commit 54db354

Browse files
committed
Merge branch 'main' into org-members-page
2 parents 87d5f5b + 01b30ea commit 54db354

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1477
-1016
lines changed

.github/actions/setup-go/action.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: |
44
inputs:
55
version:
66
description: "The Go version to use."
7-
default: "1.22.4"
7+
default: "1.22.5"
88
runs:
99
using: "composite"
1010
steps:

.github/dependabot.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ updates:
3939
prefix: "chore"
4040
labels: []
4141
open-pull-requests-limit: 15
42+
groups:
43+
x:
44+
patterns:
45+
- "golang.org/x/*"
4246
ignore:
4347
# Ignore patch updates for all dependencies
4448
- dependency-name: "*"
@@ -73,6 +77,32 @@ updates:
7377
commit-message:
7478
prefix: "chore"
7579
labels: []
80+
groups:
81+
xterm:
82+
patterns:
83+
- "@xterm*"
84+
mui:
85+
patterns:
86+
- "@mui*"
87+
react:
88+
patterns:
89+
- "react*"
90+
- "@types/react*"
91+
emotion:
92+
patterns:
93+
- "@emotion*"
94+
eslint:
95+
patterns:
96+
- "eslint*"
97+
- "@typescript-eslint*"
98+
jest:
99+
patterns:
100+
- "jest*"
101+
- "@types/jest"
102+
vite:
103+
patterns:
104+
- "vite*"
105+
- "@vitejs/plugin-react"
76106
ignore:
77107
# Ignore patch updates for all dependencies
78108
- dependency-name: "*"
@@ -83,4 +113,10 @@ updates:
83113
- dependency-name: "@types/node"
84114
update-types:
85115
- version-update:semver-major
116+
# Ignore @storybook updates, run `pnpm dlx storybook@latest upgrade` to upgrade manually
117+
- dependency-name: "*storybook*" # matches @storybook/* and storybook*
118+
update-types:
119+
- version-update:semver-major
120+
- version-update:semver-minor
121+
- version-update:semver-patch
86122
open-pull-requests-limit: 15

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ jobs:
170170
171171
# Check for any typos
172172
- name: Check for typos
173-
uses: crate-ci/typos@v1.22.9
173+
uses: crate-ci/typos@v1.23.1
174174
with:
175175
config: .github/workflows/typos.toml
176176

.github/workflows/pr-deploy.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ jobs:
101101
run: |
102102
set -euo pipefail
103103
mkdir -p ~/.kube
104-
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
104+
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG_BASE64 }}" | base64 --decode > ~/.kube/config
105105
chmod 644 ~/.kube/config
106106
export KUBECONFIG=~/.kube/config
107107
@@ -253,7 +253,7 @@ jobs:
253253
run: |
254254
set -euo pipefail
255255
mkdir -p ~/.kube
256-
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
256+
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG_BASE64 }}" | base64 --decode > ~/.kube/config
257257
chmod 644 ~/.kube/config
258258
export KUBECONFIG=~/.kube/config
259259

.github/workflows/typos.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ darcula = "darcula"
1414
Hashi = "Hashi"
1515
trialer = "trialer"
1616
encrypter = "encrypter"
17-
hel = "hel" # as in helsinki
18-
pn = "pn" # this is used as proto node
17+
# as in helsinki
18+
hel = "hel"
19+
# this is used as proto node
20+
pn = "pn"
21+
# typos doesn't like the EDE in TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
22+
EDE = "EDE"
1923

2024
[files]
2125
extend-exclude = [

cli/cliui/agent.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ func Agent(ctx context.Context, writer io.Writer, agentID uuid.UUID, opts AgentO
137137
stage += " (non-blocking)"
138138
}
139139
sw.Start(stage)
140+
if follow {
141+
sw.Log(time.Time{}, codersdk.LogLevelInfo, "==> ℹ︎ To connect immediately, reconnect with --wait=no or CODER_SSH_WAIT=no, see --help for more information.")
142+
}
140143

141144
err = func() error { // Use func because of defer in for loop.
142145
logStream, logsCloser, err := opts.FetchLogs(ctx, agent.ID, 0, follow)

cli/cliui/agent_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ func TestAgent(t *testing.T) {
226226
},
227227
want: []string{
228228
"⧗ Running workspace agent startup scripts",
229+
"ℹ︎ To connect immediately, reconnect with --wait=no or CODER_SSH_WAIT=no, see --help for more information.",
229230
"testing: Hello world",
230231
"Bye now",
231232
"✔ Running workspace agent startup scripts",
@@ -255,6 +256,7 @@ func TestAgent(t *testing.T) {
255256
},
256257
want: []string{
257258
"⧗ Running workspace agent startup scripts",
259+
"ℹ︎ To connect immediately, reconnect with --wait=no or CODER_SSH_WAIT=no, see --help for more information.",
258260
"Hello world",
259261
"✘ Running workspace agent startup scripts",
260262
"Warning: A startup script exited with an error and your workspace may be incomplete.",
@@ -306,6 +308,7 @@ func TestAgent(t *testing.T) {
306308
},
307309
want: []string{
308310
"⧗ Running workspace agent startup scripts",
311+
"ℹ︎ To connect immediately, reconnect with --wait=no or CODER_SSH_WAIT=no, see --help for more information.",
309312
"Hello world",
310313
"✔ Running workspace agent startup scripts",
311314
},

cli/configssh.go

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type sshConfigOptions struct {
5454
disableAutostart bool
5555
header []string
5656
headerCommand string
57+
removedKeys map[string]bool
5758
}
5859

5960
// addOptions expects options in the form of "option=value" or "option value".
@@ -74,30 +75,20 @@ func (o *sshConfigOptions) addOption(option string) error {
7475
if err != nil {
7576
return err
7677
}
77-
for i, existing := range o.sshOptions {
78-
// Override existing option if they share the same key.
79-
// This is case-insensitive. Parsing each time might be a little slow,
80-
// but it is ok.
81-
existingKey, _, err := codersdk.ParseSSHConfigOption(existing)
82-
if err != nil {
83-
// Don't mess with original values if there is an error.
84-
// This could have come from the user's manual edits.
85-
continue
86-
}
87-
if strings.EqualFold(existingKey, key) {
88-
if value == "" {
89-
// Delete existing option.
90-
o.sshOptions = append(o.sshOptions[:i], o.sshOptions[i+1:]...)
91-
} else {
92-
// Override existing option.
93-
o.sshOptions[i] = option
94-
}
95-
return nil
96-
}
78+
lowerKey := strings.ToLower(key)
79+
if o.removedKeys != nil && o.removedKeys[lowerKey] {
80+
// Key marked as removed, skip.
81+
return nil
9782
}
98-
// Only append the option if it is not empty.
83+
// Only append the option if it is not empty
84+
// (we interpret empty as removal).
9985
if value != "" {
10086
o.sshOptions = append(o.sshOptions, option)
87+
} else {
88+
if o.removedKeys == nil {
89+
o.removedKeys = make(map[string]bool)
90+
}
91+
o.removedKeys[lowerKey] = true
10192
}
10293
return nil
10394
}
@@ -245,6 +236,8 @@ func (r *RootCmd) configSSH() *serpent.Command {
245236
r.InitClient(client),
246237
),
247238
Handler: func(inv *serpent.Invocation) error {
239+
ctx := inv.Context()
240+
248241
if sshConfigOpts.waitEnum != "auto" && skipProxyCommand {
249242
// The wait option is applied to the ProxyCommand. If the user
250243
// specifies skip-proxy-command, then wait cannot be applied.
@@ -253,7 +246,14 @@ func (r *RootCmd) configSSH() *serpent.Command {
253246
sshConfigOpts.header = r.header
254247
sshConfigOpts.headerCommand = r.headerCommand
255248

256-
recvWorkspaceConfigs := sshPrepareWorkspaceConfigs(inv.Context(), client)
249+
// Talk to the API early to prevent the version mismatch
250+
// warning from being printed in the middle of a prompt.
251+
// This is needed because the asynchronous requests issued
252+
// by sshPrepareWorkspaceConfigs may otherwise trigger the
253+
// warning at any time.
254+
_, _ = client.BuildInfo(ctx)
255+
256+
recvWorkspaceConfigs := sshPrepareWorkspaceConfigs(ctx, client)
257257

258258
out := inv.Stdout
259259
if dryRun {
@@ -375,7 +375,7 @@ func (r *RootCmd) configSSH() *serpent.Command {
375375
return xerrors.Errorf("fetch workspace configs failed: %w", err)
376376
}
377377

378-
coderdConfig, err := client.SSHConfiguration(inv.Context())
378+
coderdConfig, err := client.SSHConfiguration(ctx)
379379
if err != nil {
380380
// If the error is 404, this deployment does not support
381381
// this endpoint yet. Do not error, just assume defaults.
@@ -440,26 +440,29 @@ func (r *RootCmd) configSSH() *serpent.Command {
440440
configOptions := sshConfigOpts
441441
configOptions.sshOptions = nil
442442

443-
// Add standard options.
444-
err := configOptions.addOptions(defaultOptions...)
445-
if err != nil {
446-
return err
443+
// User options first (SSH only uses the first
444+
// option unless it can be given multiple times)
445+
for _, opt := range sshConfigOpts.sshOptions {
446+
err := configOptions.addOptions(opt)
447+
if err != nil {
448+
return xerrors.Errorf("add flag config option %q: %w", opt, err)
449+
}
447450
}
448451

449-
// Override with deployment options
452+
// Deployment options second, allow them to
453+
// override standard options.
450454
for k, v := range coderdConfig.SSHConfigOptions {
451455
opt := fmt.Sprintf("%s %s", k, v)
452456
err := configOptions.addOptions(opt)
453457
if err != nil {
454458
return xerrors.Errorf("add coderd config option %q: %w", opt, err)
455459
}
456460
}
457-
// Override with flag options
458-
for _, opt := range sshConfigOpts.sshOptions {
459-
err := configOptions.addOptions(opt)
460-
if err != nil {
461-
return xerrors.Errorf("add flag config option %q: %w", opt, err)
462-
}
461+
462+
// Finally, add the standard options.
463+
err := configOptions.addOptions(defaultOptions...)
464+
if err != nil {
465+
return err
463466
}
464467

465468
hostBlock := []string{

cli/configssh_internal_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,32 +272,32 @@ func Test_sshConfigOptions_addOption(t *testing.T) {
272272
},
273273
},
274274
{
275-
Name: "Replace",
275+
Name: "AddTwo",
276276
Start: []string{
277277
"foo bar",
278278
},
279279
Add: []string{"Foo baz"},
280280
Expect: []string{
281+
"foo bar",
281282
"Foo baz",
282283
},
283284
},
284285
{
285-
Name: "AddAndReplace",
286+
Name: "AddAndRemove",
286287
Start: []string{
287-
"a b",
288288
"foo bar",
289289
"buzz bazz",
290290
},
291291
Add: []string{
292292
"b c",
293+
"a ", // Empty value, means remove all following entries that start with "a", i.e. next line.
293294
"A hello",
294295
"hello world",
295296
},
296297
Expect: []string{
297298
"foo bar",
298299
"buzz bazz",
299300
"b c",
300-
"A hello",
301301
"hello world",
302302
},
303303
},

cli/configssh_test.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func TestConfigSSH(t *testing.T) {
6565

6666
const hostname = "test-coder."
6767
const expectedKey = "ConnectionAttempts"
68-
const removeKey = "ConnectionTimeout"
68+
const removeKey = "ConnectTimeout"
6969
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
7070
ConfigSSH: codersdk.SSHConfigResponse{
7171
HostnamePrefix: hostname,
@@ -620,6 +620,19 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
620620
regexMatch: `ProxyCommand .* --header-command "printf h1=v1 h2='v2'" ssh`,
621621
},
622622
},
623+
{
624+
name: "Multiple remote forwards",
625+
args: []string{
626+
"--yes",
627+
"--ssh-option", "RemoteForward 2222 192.168.11.1:2222",
628+
"--ssh-option", "RemoteForward 2223 192.168.11.1:2223",
629+
},
630+
wantErr: false,
631+
hasAgent: true,
632+
wantConfig: wantConfig{
633+
regexMatch: "RemoteForward 2222 192.168.11.1:2222.*\n.*RemoteForward 2223 192.168.11.1:2223",
634+
},
635+
},
623636
}
624637
for _, tt := range tests {
625638
tt := tt

cli/server.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,19 @@ func generateSelfSignedCertificate() (*tls.Certificate, error) {
15691569
return &cert, nil
15701570
}
15711571

1572+
// defaultCipherSuites is a list of safe cipher suites that we default to. This
1573+
// is different from Golang's list of defaults, which unfortunately includes
1574+
// `TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA`.
1575+
var defaultCipherSuites = func() []uint16 {
1576+
ret := []uint16{}
1577+
1578+
for _, suite := range tls.CipherSuites() {
1579+
ret = append(ret, suite.ID)
1580+
}
1581+
1582+
return ret
1583+
}()
1584+
15721585
// configureServerTLS returns the TLS config used for the Coderd server
15731586
// connections to clients. A logger is passed in to allow printing warning
15741587
// messages that do not block startup.
@@ -1599,6 +1612,8 @@ func configureServerTLS(ctx context.Context, logger slog.Logger, tlsMinVersion,
15991612
return nil, err
16001613
}
16011614
tlsConfig.CipherSuites = cipherIDs
1615+
} else {
1616+
tlsConfig.CipherSuites = defaultCipherSuites
16021617
}
16031618

16041619
switch tlsClientAuth {

cli/server_internal_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,28 @@ import (
2020
"github.com/coder/serpent"
2121
)
2222

23+
func Test_configureServerTLS(t *testing.T) {
24+
t.Parallel()
25+
t.Run("DefaultNoInsecureCiphers", func(t *testing.T) {
26+
t.Parallel()
27+
logger := slogtest.Make(t, nil)
28+
cfg, err := configureServerTLS(context.Background(), logger, "tls12", "none", nil, nil, "", nil, false)
29+
require.NoError(t, err)
30+
31+
require.NotEmpty(t, cfg)
32+
33+
insecureCiphers := tls.InsecureCipherSuites()
34+
for _, cipher := range cfg.CipherSuites {
35+
for _, insecure := range insecureCiphers {
36+
if cipher == insecure.ID {
37+
t.Logf("Insecure cipher found by default: %s", insecure.Name)
38+
t.Fail()
39+
}
40+
}
41+
}
42+
})
43+
}
44+
2345
func Test_configureCipherSuites(t *testing.T) {
2446
t.Parallel()
2547

0 commit comments

Comments
 (0)