Skip to content

Commit fc992cd

Browse files
committed
gerge remote-tracking branch 'origin/main' into authzquerier_layer
2 parents 6a7b053 + 8ef0306 commit fc992cd

Some content is hidden

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

47 files changed

+1872
-136
lines changed

.github/workflows/typos.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ MacOS = "macOS"
66
AKS = "AKS"
77

88
[default.extend-words]
9+
AKS = "AKS"
910
# do as sudo replacement
1011
doas = "doas"
1112
darcula = "darcula"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
[![discord](https://img.shields.io/discord/747933592273027093?label=discord)](https://discord.gg/coder)
2626
[![codecov](https://codecov.io/gh/coder/coder/branch/main/graph/badge.svg?token=TNLW3OAP6G)](https://codecov.io/gh/coder/coder)
27-
[![release](https://img.shields.io/github/v/release/coder/coder)](https://github.com/coder/coder/releases)
27+
[![release](https://img.shields.io/github/v/release/coder/coder)](https://github.com/coder/coder/releases/latest)
2828
[![godoc](https://pkg.go.dev/badge/github.com/coder/coder.svg)](https://pkg.go.dev/github.com/coder/coder)
2929
[![Go Report Card](https://goreportcard.com/badge/github.com/coder/coder)](https://goreportcard.com/report/github.com/coder/coder)
3030
[![license](https://img.shields.io/github/license/coder/coder)](./LICENSE)

agent/agent.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -526,23 +526,23 @@ func (a *agent) createTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) (_
526526
return nil, err
527527
}
528528

529-
statisticsListener, err := network.Listen("tcp", ":"+strconv.Itoa(codersdk.WorkspaceAgentStatisticsPort))
529+
apiListener, err := network.Listen("tcp", ":"+strconv.Itoa(codersdk.WorkspaceAgentHTTPAPIServerPort))
530530
if err != nil {
531-
return nil, xerrors.Errorf("listen for statistics: %w", err)
531+
return nil, xerrors.Errorf("api listener: %w", err)
532532
}
533533
defer func() {
534534
if err != nil {
535-
_ = statisticsListener.Close()
535+
_ = apiListener.Close()
536536
}
537537
}()
538538
if err = a.trackConnGoroutine(func() {
539-
defer statisticsListener.Close()
539+
defer apiListener.Close()
540540
server := &http.Server{
541-
Handler: a.statisticsHandler(),
541+
Handler: a.apiHandler(),
542542
ReadTimeout: 20 * time.Second,
543543
ReadHeaderTimeout: 20 * time.Second,
544544
WriteTimeout: 20 * time.Second,
545-
ErrorLog: slog.Stdlib(ctx, a.logger.Named("statistics_http_server"), slog.LevelInfo),
545+
ErrorLog: slog.Stdlib(ctx, a.logger.Named("http_api_server"), slog.LevelInfo),
546546
}
547547
go func() {
548548
select {
@@ -552,9 +552,9 @@ func (a *agent) createTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) (_
552552
_ = server.Close()
553553
}()
554554

555-
err := server.Serve(statisticsListener)
555+
err := server.Serve(apiListener)
556556
if err != nil && !xerrors.Is(err, http.ErrServerClosed) && !strings.Contains(err.Error(), "use of closed network connection") {
557-
a.logger.Critical(ctx, "serve statistics HTTP server", slog.Error(err))
557+
a.logger.Critical(ctx, "serve HTTP API server", slog.Error(err))
558558
}
559559
}); err != nil {
560560
return nil, err

agent/statsendpoint.go renamed to agent/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/coder/coder/codersdk"
1212
)
1313

14-
func (*agent) statisticsHandler() http.Handler {
14+
func (*agent) apiHandler() http.Handler {
1515
r := chi.NewRouter()
1616
r.Get("/", func(rw http.ResponseWriter, r *http.Request) {
1717
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.Response{

cli/agent.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package cli
33
import (
44
"context"
55
"fmt"
6+
"io"
67
"net/http"
78
"net/http/pprof"
89
"net/url"
910
"os"
1011
"os/signal"
1112
"path/filepath"
1213
"runtime"
14+
"sync"
1315
"time"
1416

1517
"cloud.google.com/go/compute/metadata"
@@ -91,11 +93,14 @@ func workspaceAgent() *cobra.Command {
9193
// reaper.
9294
go dumpHandler(ctx)
9395

94-
logWriter := &lumberjack.Logger{
96+
ljLogger := &lumberjack.Logger{
9597
Filename: filepath.Join(logDir, "coder-agent.log"),
9698
MaxSize: 5, // MB
9799
}
100+
defer ljLogger.Close()
101+
logWriter := &closeWriter{w: ljLogger}
98102
defer logWriter.Close()
103+
99104
logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()), sloghuman.Sink(logWriter)).Leveled(slog.LevelDebug)
100105

101106
version := buildinfo.Version()
@@ -229,3 +234,30 @@ func serveHandler(ctx context.Context, logger slog.Logger, handler http.Handler,
229234
_ = srv.Close()
230235
}
231236
}
237+
238+
// closeWriter is a wrapper around an io.WriteCloser that prevents
239+
// writes after Close. This is necessary because lumberjack will
240+
// re-open the file on write.
241+
type closeWriter struct {
242+
w io.WriteCloser
243+
mu sync.Mutex // Protects following.
244+
closed bool
245+
}
246+
247+
func (c *closeWriter) Close() error {
248+
c.mu.Lock()
249+
defer c.mu.Unlock()
250+
251+
c.closed = true
252+
return c.w.Close()
253+
}
254+
255+
func (c *closeWriter) Write(p []byte) (int, error) {
256+
c.mu.Lock()
257+
defer c.mu.Unlock()
258+
259+
if c.closed {
260+
return 0, io.ErrClosedPipe
261+
}
262+
return c.w.Write(p)
263+
}

codersdk/workspaceagentconn.go

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,18 @@ import (
2323
"github.com/coder/coder/tailnet"
2424
)
2525

26-
var (
27-
// WorkspaceAgentIP is a static IPv6 address with the Tailscale prefix that is used to route
28-
// connections from clients to this node. A dynamic address is not required because a Tailnet
29-
// client only dials a single agent at a time.
30-
WorkspaceAgentIP = netip.MustParseAddr("fd7a:115c:a1e0:49d6:b259:b7ac:b1b2:48f4")
31-
)
26+
// WorkspaceAgentIP is a static IPv6 address with the Tailscale prefix that is used to route
27+
// connections from clients to this node. A dynamic address is not required because a Tailnet
28+
// client only dials a single agent at a time.
29+
var WorkspaceAgentIP = netip.MustParseAddr("fd7a:115c:a1e0:49d6:b259:b7ac:b1b2:48f4")
3230

3331
const (
3432
WorkspaceAgentSSHPort = 1
3533
WorkspaceAgentReconnectingPTYPort = 2
3634
WorkspaceAgentSpeedtestPort = 3
37-
// WorkspaceAgentStatisticsPort serves a HTTP server with endpoints for gathering
38-
// agent statistics.
39-
WorkspaceAgentStatisticsPort = 4
35+
// WorkspaceAgentHTTPAPIServerPort serves a HTTP server with endpoints for e.g.
36+
// gathering agent statistics.
37+
WorkspaceAgentHTTPAPIServerPort = 4
4038

4139
// WorkspaceAgentMinimumListeningPort is the minimum port that the listening-ports
4240
// endpoint will return to the client, and the minimum port that is accepted
@@ -282,7 +280,7 @@ type WorkspaceAgentListeningPort struct {
282280
func (c *WorkspaceAgentConn) ListeningPorts(ctx context.Context) (WorkspaceAgentListeningPortsResponse, error) {
283281
ctx, span := tracing.StartSpan(ctx)
284282
defer span.End()
285-
res, err := c.requestStatisticsServer(ctx, http.MethodGet, "/api/v0/listening-ports", nil)
283+
res, err := c.apiRequest(ctx, http.MethodGet, "/api/v0/listening-ports", nil)
286284
if err != nil {
287285
return WorkspaceAgentListeningPortsResponse{}, xerrors.Errorf("do request: %w", err)
288286
}
@@ -295,30 +293,30 @@ func (c *WorkspaceAgentConn) ListeningPorts(ctx context.Context) (WorkspaceAgent
295293
return resp, json.NewDecoder(res.Body).Decode(&resp)
296294
}
297295

298-
// requestStatisticsServer makes a request to the workspace agent's statistics server.
299-
func (c *WorkspaceAgentConn) requestStatisticsServer(ctx context.Context, method, path string, body io.Reader) (*http.Response, error) {
296+
// apiRequest makes a request to the workspace agent's HTTP API server.
297+
func (c *WorkspaceAgentConn) apiRequest(ctx context.Context, method, path string, body io.Reader) (*http.Response, error) {
300298
ctx, span := tracing.StartSpan(ctx)
301299
defer span.End()
302-
host := net.JoinHostPort(WorkspaceAgentIP.String(), strconv.Itoa(WorkspaceAgentStatisticsPort))
300+
host := net.JoinHostPort(WorkspaceAgentIP.String(), strconv.Itoa(WorkspaceAgentHTTPAPIServerPort))
303301
url := fmt.Sprintf("http://%s%s", host, path)
304302

305303
req, err := http.NewRequestWithContext(ctx, method, url, body)
306304
if err != nil {
307-
return nil, xerrors.Errorf("new statistics server request to %q: %w", url, err)
305+
return nil, xerrors.Errorf("new http api request to %q: %w", url, err)
308306
}
309307

310-
return c.statisticsServerClient().Do(req)
308+
return c.apiClient().Do(req)
311309
}
312310

313-
// statisticsServerClient returns an HTTP client that can be used to make
314-
// requests to the workspace agent's statistics server.
315-
func (c *WorkspaceAgentConn) statisticsServerClient() *http.Client {
311+
// apiClient returns an HTTP client that can be used to make
312+
// requests to the workspace agent's HTTP API server.
313+
func (c *WorkspaceAgentConn) apiClient() *http.Client {
316314
return &http.Client{
317315
Transport: &http.Transport{
318316
// Disable keep alives as we're usually only making a single
319317
// request, and this triggers goleak in tests
320318
DisableKeepAlives: true,
321-
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
319+
DialContext: func(_ context.Context, network, addr string) (net.Conn, error) {
322320
if network != "tcp" {
323321
return nil, xerrors.Errorf("network must be tcp")
324322
}
@@ -328,13 +326,13 @@ func (c *WorkspaceAgentConn) statisticsServerClient() *http.Client {
328326
}
329327
// Verify that host is TailnetIP and port is
330328
// TailnetStatisticsPort.
331-
if host != WorkspaceAgentIP.String() || port != strconv.Itoa(WorkspaceAgentStatisticsPort) {
332-
return nil, xerrors.Errorf("request %q does not appear to be for statistics server", addr)
329+
if host != WorkspaceAgentIP.String() || port != strconv.Itoa(WorkspaceAgentHTTPAPIServerPort) {
330+
return nil, xerrors.Errorf("request %q does not appear to be for http api", addr)
333331
}
334332

335-
conn, err := c.DialContextTCP(context.Background(), netip.AddrPortFrom(WorkspaceAgentIP, WorkspaceAgentStatisticsPort))
333+
conn, err := c.DialContextTCP(context.Background(), netip.AddrPortFrom(WorkspaceAgentIP, WorkspaceAgentHTTPAPIServerPort))
336334
if err != nil {
337-
return nil, xerrors.Errorf("dial statistics: %w", err)
335+
return nil, xerrors.Errorf("dial http api: %w", err)
338336
}
339337

340338
return conn, nil

docs/admin/upgrade.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ See [Upgrading Coder via Helm](../install/kubernetes.md#upgrading-coder-via-helm
4545

4646
## Via Windows
4747

48-
Download the latest Windows installer or binary from [GitHub releases](https://github.com/coder/coder/releases), or upgrade from Winget.
48+
Download the latest Windows installer or binary from [GitHub releases](https://github.com/coder/coder/releases/latest), or upgrade from Winget.
4949

5050
```sh
5151
winget install Coder.Coder

docs/admin/users.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ with the user so that they can log into Coder:
4646

4747
```console
4848
Download the Coder command line for your operating system:
49-
https://github.com/coder/coder/releases
49+
https://github.com/coder/coder/releases/latest
5050

5151
Run coder login https://<accessURL>.coder.app to authenticate.
5252

docs/install/binary.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
Coder publishes self-contained .zip and .tar.gz archives in [GitHub releases](https://github.com/coder/coder/releases). The archives bundle `coder` binary.
1+
Coder publishes self-contained .zip and .tar.gz archives in [GitHub releases](https://github.com/coder//latest). The archives bundle `coder` binary.
22

3-
1. Download the [release archive](https://github.com/coder/coder/releases) appropriate for your operating system
3+
1. Download the [release archive](https://github.com/coder/coder/releases/latest) appropriate for your operating system
44

55
1. Unzip the folder you just downloaded, and move the `coder` executable to a location that's on your `PATH`
66

docs/install/kubernetes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Before proceeding, please ensure that you have a Kubernetes cluster running K8s 1.19+ and have Helm 3.5+ installed.
44

5-
You'll also want to install the [latest version of Coder](https://github.com/coder/coder/releases) locally in order
5+
You'll also want to install the [latest version of Coder](https://github.com/coder/coder/releases/latest) locally in order
66
to log in and manage templates.
77

88
## Install Coder with Helm

docs/install/offline.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ services:
133133
134134
## Run offline via Kubernetes
135135

136-
We publish the Helm chart for download on [GitHub Releases](https://github.com/coder/coder/releases). Follow our [Kubernetes](./kubernetes.md) documentation and modify the Helm values to specify your custom Coder image.
136+
We publish the Helm chart for download on [GitHub Releases](https://github.com/coder/coder/releases/latest). Follow our [Kubernetes](./kubernetes.md) documentation and modify the Helm values to specify your custom Coder image.
137137

138138
```yaml
139139
# values.yaml

docs/install/packages.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1. Download and install one of the following system packages from [GitHub releases](https://github.com/coder/coder/releases):
1+
1. Download and install one of the following system packages from [GitHub releases](https://github.com/coder/coder/releases/latest):
22

33
- .deb (Debian, Ubuntu)
44
- .rpm (Fedora, CentOS, RHEL, SUSE)

docs/install/windows.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Use the Windows installer to download the CLI and add Coder to `PATH`. Alternatively, you can install Coder on Windows via a [standalone binary](./binary.md).
44

5-
1. Download the Windows installer from [GitHub releases](https://github.com/coder/coder/releases) or from `winget`
5+
1. Download the Windows installer from [GitHub releases](https://github.com/coder/coder/releases/latest) or from `winget`
66

77
```powershell
88
winget install Coder.Coder

docs/secrets.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<blockquote class="info">
44
This article explains how to use secrets in a workspace. To authenticate the
5-
workspace provisioner, see [this](./admin/auth.md).
5+
workspace provisioner, see <a href="/admin/auth">this</a>.
66
</blockquote>
77

88
Coder is open-minded about how you get your secrets into your workspaces.

docs/templates.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The CLI and the server are the same binary. We did this to encourage virality so
1515
individuals can start their own Coder deployments.
1616

1717
From your local machine, download the CLI for your operating system from the
18-
[releases](https://github.com/coder/coder/releases) or run:
18+
[releases](https://github.com/coder/coder/releases/latest) or run:
1919

2020
```console
2121
curl -fsSL https://coder.com/install.sh | sh

docs/templates/docker-in-docker.md

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
# Docker in Docker
2+
13
There are a few ways to run Docker within container-based Coder workspaces.
24

3-
## Sysbox runtime (recommended)
5+
| Method | Description | Limitations |
6+
| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
7+
| [Sysbox container runtime](#sysbox-container-runtime) | Install sysbox on your Kubernetes nodes for secure docker-in-docker and systemd-in-docker. Works with GKE, EKS, AKS. | Requires [compatible nodes](https://github.com/nestybox/sysbox#host-requirements). Max of 16 sysbox pods per node. [See all](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/limitations.md) |
8+
| [Privileged docker sidecar](#privileged-sidecar-container) | Run docker as a privilged sidecar container. | Requires a privileged container. Workspaces can break out to root on the host machine. |
49

5-
The [Sysbox](https://github.com/nestybox/sysbox) container runtime allows unprivileged users to run system-level applications, such as Docker, securely from the workspace containers. Sysbox requires a [compatible Linux distribution](https://github.com/nestybox/sysbox/blob/master/docs/distro-compat.md) to implement these security features.
10+
## Sysbox container runtime
611

7-
> Sysbox can also be used to run systemd inside Coder workspaces. See [Systemd in Docker](#systemd-in-docker).
12+
The [Sysbox](https://github.com/nestybox/sysbox) container runtime allows unprivileged users to run system-level applications, such as Docker, securely from the workspace containers. Sysbox requires a [compatible Linux distribution](https://github.com/nestybox/sysbox/blob/master/docs/distro-compat.md) to implement these security features. Sysbox can also be used to run systemd inside Coder workspaces. See [Systemd in Docker](#systemd-in-docker).
813

914
### Use Sysbox in Docker-based templates
1015

@@ -106,7 +111,9 @@ resource "kubernetes_pod" "dev" {
106111
107112
## Privileged sidecar container
108113

109-
While less secure, you can attach a [privileged container](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) to your templates. This may come in handy if your nodes cannot run Sysbox.
114+
A [privileged container](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) can be added to your templates to add docker support. This may come in handy if your nodes cannot run Sysbox.
115+
116+
> ⚠️ **Warning**: This is insecure. Workspaces will be able to gain root access to the host machine.
110117
111118
### Use a privileged sidecar container in Docker-based templates
112119

@@ -212,48 +219,6 @@ resource "kubernetes_pod" "main" {
212219

213220
Additionally, [Sysbox](https://github.com/nestybox/sysbox) can be used to give workspaces full `systemd` capabilities.
214221

215-
### Use systemd in Docker-based templates
216-
217-
After [installing Sysbox](https://github.com/nestybox/sysbox#installation) on the Coder host, modify your template to use the sysbox-runc runtime and start systemd:
218-
219-
```hcl
220-
resource "docker_container" "workspace" {
221-
image = "codercom/enterprise-base:ubuntu"
222-
name = "coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}"
223-
224-
# Use Sysbox container runtime (required)
225-
runtime = "sysbox-runc"
226-
# Run as root in order to start systemd (required)
227-
user = "0:0"
228-
229-
# Start systemd and the Coder agent
230-
command = ["sh", "-c", <<EOF
231-
# Start the Coder agent as the "coder" user
232-
# once systemd has started up
233-
sudo -u coder --preserve-env=CODER_AGENT_TOKEN /bin/bash -- <<-' EOT' &
234-
while [[ ! $(systemctl is-system-running) =~ ^(running|degraded) ]]
235-
do
236-
echo "Waiting for system to start... $(systemctl is-system-running)"
237-
sleep 2
238-
done
239-
${coder_agent.main.init_script}
240-
EOT
241-
242-
exec /sbin/init
243-
EOF
244-
,
245-
]
246-
env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
247-
}
248-
249-
resource "coder_agent" "main" {
250-
arch = data.coder_provisioner.me.arch
251-
os = "linux"
252-
}
253-
```
254-
255-
### Use systemd in Kubernetes-based templates
256-
257222
After [installing Sysbox on Kubernetes](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/install-k8s.md),
258223
modify your template to use the sysbox-runc RuntimeClass. This requires the Kubernetes Terraform provider version 2.16.0 or greater.
259224

scaletest/agentconn/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func verifyConnection(ctx context.Context, logs io.Writer, conn *codersdk.Worksp
218218

219219
u := &url.URL{
220220
Scheme: "http",
221-
Host: net.JoinHostPort("localhost", strconv.Itoa(codersdk.WorkspaceAgentStatisticsPort)),
221+
Host: net.JoinHostPort("localhost", strconv.Itoa(codersdk.WorkspaceAgentHTTPAPIServerPort)),
222222
Path: "/",
223223
}
224224
req, err := http.NewRequestWithContext(verifyCtx, http.MethodGet, u.String(), nil)

0 commit comments

Comments
 (0)