Skip to content

Commit ebd3032

Browse files
authored
Merge branch 'main' into dormant-users-groups/kira-pilot
2 parents 4799bfb + 9c9319f commit ebd3032

File tree

113 files changed

+3465
-2135
lines changed

Some content is hidden

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

113 files changed

+3465
-2135
lines changed

cli/server.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import (
4141
"github.com/prometheus/client_golang/prometheus"
4242
"github.com/prometheus/client_golang/prometheus/collectors"
4343
"github.com/prometheus/client_golang/prometheus/promhttp"
44+
"go.opentelemetry.io/otel"
45+
"go.opentelemetry.io/otel/propagation"
4446
"go.opentelemetry.io/otel/trace"
4547
"golang.org/x/mod/semver"
4648
"golang.org/x/oauth2"
@@ -78,6 +80,7 @@ import (
7880
"github.com/coder/coder/v2/coderd/httpmw"
7981
"github.com/coder/coder/v2/coderd/oauthpki"
8082
"github.com/coder/coder/v2/coderd/prometheusmetrics"
83+
"github.com/coder/coder/v2/coderd/prometheusmetrics/insights"
8184
"github.com/coder/coder/v2/coderd/schedule"
8285
"github.com/coder/coder/v2/coderd/telemetry"
8386
"github.com/coder/coder/v2/coderd/tracing"
@@ -198,6 +201,21 @@ func enablePrometheus(
198201
}
199202
afterCtx(ctx, closeWorkspacesFunc)
200203

204+
insightsMetricsCollector, err := insights.NewMetricsCollector(options.Database, options.Logger, 0, 0)
205+
if err != nil {
206+
return nil, xerrors.Errorf("unable to initialize insights metrics collector: %w", err)
207+
}
208+
err = options.PrometheusRegistry.Register(insightsMetricsCollector)
209+
if err != nil {
210+
return nil, xerrors.Errorf("unable to register insights metrics collector: %w", err)
211+
}
212+
213+
closeInsightsMetricsCollector, err := insightsMetricsCollector.Run(ctx)
214+
if err != nil {
215+
return nil, xerrors.Errorf("unable to run insights metrics collector: %w", err)
216+
}
217+
afterCtx(ctx, closeInsightsMetricsCollector)
218+
201219
if vals.Prometheus.CollectAgentStats {
202220
closeAgentStatsFunc, err := prometheusmetrics.AgentStats(ctx, logger, options.PrometheusRegistry, options.Database, time.Now(), 0)
203221
if err != nil {
@@ -938,7 +956,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
938956
autobuildTicker := time.NewTicker(vals.AutobuildPollInterval.Value())
939957
defer autobuildTicker.Stop()
940958
autobuildExecutor := autobuild.NewExecutor(
941-
ctx, options.Database, options.Pubsub, coderAPI.TemplateScheduleStore, &coderAPI.Auditor, logger, autobuildTicker.C)
959+
ctx, options.Database, options.Pubsub, coderAPI.TemplateScheduleStore, &coderAPI.Auditor, coderAPI.AccessControlStore, logger, autobuildTicker.C)
942960
autobuildExecutor.Run()
943961

944962
hangDetectorTicker := time.NewTicker(vals.JobHangDetectorInterval.Value())
@@ -2020,6 +2038,13 @@ func ConfigureTraceProvider(
20202038
sqlDriver = "postgres"
20212039
)
20222040

2041+
otel.SetTextMapPropagator(
2042+
propagation.NewCompositeTextMapPropagator(
2043+
propagation.TraceContext{},
2044+
propagation.Baggage{},
2045+
),
2046+
)
2047+
20232048
if cfg.Trace.Enable.Value() || cfg.Trace.DataDog.Value() || cfg.Trace.HoneycombAPIKey != "" {
20242049
sdkTracerProvider, _closeTracing, err := tracing.TracerProvider(ctx, "coderd", tracing.TracerOpts{
20252050
Default: cfg.Trace.Enable.Value(),

cli/templates.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ import (
66
"github.com/google/uuid"
77
"golang.org/x/xerrors"
88

9-
"github.com/coder/pretty"
10-
119
"github.com/coder/coder/v2/cli/clibase"
1210
"github.com/coder/coder/v2/cli/cliui"
1311
"github.com/coder/coder/v2/codersdk"
12+
"github.com/coder/pretty"
1413
)
1514

1615
func (r *RootCmd) templates() *clibase.Cmd {

cli/templateversionarchive.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ import (
88

99
"golang.org/x/xerrors"
1010

11-
"github.com/coder/pretty"
12-
1311
"github.com/coder/coder/v2/cli/clibase"
1412
"github.com/coder/coder/v2/cli/cliui"
1513
"github.com/coder/coder/v2/codersdk"
14+
"github.com/coder/pretty"
1615
)
1716

1817
func (r *RootCmd) unarchiveTemplateVersion() *clibase.Cmd {

cli/templateversions.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ import (
88
"github.com/google/uuid"
99
"golang.org/x/xerrors"
1010

11-
"github.com/coder/pretty"
12-
1311
"github.com/coder/coder/v2/cli/clibase"
1412
"github.com/coder/coder/v2/cli/cliui"
1513
"github.com/coder/coder/v2/codersdk"
14+
"github.com/coder/pretty"
1615
)
1716

1817
func (r *RootCmd) templateVersions() *clibase.Cmd {

cli/user_delete_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ func TestUserDelete(t *testing.T) {
121121
// pw, err := cryptorand.String(16)
122122
// require.NoError(t, err)
123123

124-
// fmt.Println(aUser.OrganizationID)
125124
// toDelete, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
126125
// Email: "colin5@coder.com",
127126
// Username: "coolin",

coderd/apidoc/docs.go

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/audit/request.go

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111

1212
"github.com/google/uuid"
1313
"github.com/sqlc-dev/pqtype"
14+
"go.opentelemetry.io/otel/baggage"
15+
"golang.org/x/xerrors"
1416

1517
"cdr.dev/slog"
1618
"github.com/coder/coder/v2/coderd/database"
@@ -54,6 +56,7 @@ type BuildAuditParams[T Auditable] struct {
5456
Status int
5557
Action database.AuditAction
5658
OrganizationID uuid.UUID
59+
IP string
5760
AdditionalFields json.RawMessage
5861

5962
New T
@@ -248,9 +251,7 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request
248251
// WorkspaceBuildAudit creates an audit log for a workspace build.
249252
// The audit log is committed upon invocation.
250253
func WorkspaceBuildAudit[T Auditable](ctx context.Context, p *BuildAuditParams[T]) {
251-
// As the audit request has not been initiated directly by a user, we omit
252-
// certain user details.
253-
ip := parseIP("")
254+
ip := parseIP(p.IP)
254255

255256
diff := Diff(p.Audit, p.Old, p.New)
256257
var err error
@@ -280,16 +281,70 @@ func WorkspaceBuildAudit[T Auditable](ctx context.Context, p *BuildAuditParams[T
280281
RequestID: p.JobID,
281282
AdditionalFields: p.AdditionalFields,
282283
}
283-
exportErr := p.Audit.Export(ctx, auditLog)
284-
if exportErr != nil {
284+
err = p.Audit.Export(ctx, auditLog)
285+
if err != nil {
285286
p.Log.Error(ctx, "export audit log",
286287
slog.F("audit_log", auditLog),
287288
slog.Error(err),
288289
)
289-
return
290290
}
291291
}
292292

293+
type WorkspaceBuildBaggage struct {
294+
IP string
295+
}
296+
297+
func (b WorkspaceBuildBaggage) Props() ([]baggage.Property, error) {
298+
ipProp, err := baggage.NewKeyValueProperty("ip", b.IP)
299+
if err != nil {
300+
return nil, xerrors.Errorf("create ip kv property: %w", err)
301+
}
302+
303+
return []baggage.Property{ipProp}, nil
304+
}
305+
306+
func WorkspaceBuildBaggageFromRequest(r *http.Request) WorkspaceBuildBaggage {
307+
return WorkspaceBuildBaggage{IP: r.RemoteAddr}
308+
}
309+
310+
type Baggage interface {
311+
Props() ([]baggage.Property, error)
312+
}
313+
314+
func BaggageToContext(ctx context.Context, d Baggage) (context.Context, error) {
315+
props, err := d.Props()
316+
if err != nil {
317+
return ctx, xerrors.Errorf("create baggage properties: %w", err)
318+
}
319+
320+
m, err := baggage.NewMember("audit", "baggage", props...)
321+
if err != nil {
322+
return ctx, xerrors.Errorf("create new baggage member: %w", err)
323+
}
324+
325+
b, err := baggage.New(m)
326+
if err != nil {
327+
return ctx, xerrors.Errorf("create new baggage carrier: %w", err)
328+
}
329+
330+
return baggage.ContextWithBaggage(ctx, b), nil
331+
}
332+
333+
func BaggageFromContext(ctx context.Context) WorkspaceBuildBaggage {
334+
d := WorkspaceBuildBaggage{}
335+
b := baggage.FromContext(ctx)
336+
props := b.Member("audit").Properties()
337+
for _, prop := range props {
338+
switch prop.Key() {
339+
case "ip":
340+
d.IP, _ = prop.Value()
341+
default:
342+
}
343+
}
344+
345+
return d
346+
}
347+
293348
func either[T Auditable, R any](old, new T, fn func(T) R, auditAction database.AuditAction) R {
294349
if ResourceID(new) != uuid.Nil {
295350
return fn(new)

coderd/audit/request_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package audit_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
"go.opentelemetry.io/otel/propagation"
9+
10+
"github.com/coder/coder/v2/coderd/audit"
11+
)
12+
13+
func TestBaggage(t *testing.T) {
14+
t.Parallel()
15+
prop := propagation.NewCompositeTextMapPropagator(
16+
propagation.TraceContext{},
17+
propagation.Baggage{},
18+
)
19+
20+
expected := audit.WorkspaceBuildBaggage{
21+
IP: "127.0.0.1",
22+
}
23+
24+
ctx, err := audit.BaggageToContext(context.Background(), expected)
25+
require.NoError(t, err)
26+
27+
carrier := propagation.MapCarrier{}
28+
prop.Inject(ctx, carrier)
29+
bCtx := prop.Extract(ctx, carrier)
30+
got := audit.BaggageFromContext(bCtx)
31+
32+
require.Equal(t, expected, got)
33+
}

coderd/autobuild/lifecycle_executor.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type Executor struct {
3232
db database.Store
3333
ps pubsub.Pubsub
3434
templateScheduleStore *atomic.Pointer[schedule.TemplateScheduleStore]
35+
accessControlStore *atomic.Pointer[dbauthz.AccessControlStore]
3536
auditor *atomic.Pointer[audit.Auditor]
3637
log slog.Logger
3738
tick <-chan time.Time
@@ -46,7 +47,7 @@ type Stats struct {
4647
}
4748

4849
// New returns a new wsactions executor.
49-
func NewExecutor(ctx context.Context, db database.Store, ps pubsub.Pubsub, tss *atomic.Pointer[schedule.TemplateScheduleStore], auditor *atomic.Pointer[audit.Auditor], log slog.Logger, tick <-chan time.Time) *Executor {
50+
func NewExecutor(ctx context.Context, db database.Store, ps pubsub.Pubsub, tss *atomic.Pointer[schedule.TemplateScheduleStore], auditor *atomic.Pointer[audit.Auditor], acs *atomic.Pointer[dbauthz.AccessControlStore], log slog.Logger, tick <-chan time.Time) *Executor {
5051
le := &Executor{
5152
//nolint:gocritic // Autostart has a limited set of permissions.
5253
ctx: dbauthz.AsAutostart(ctx),
@@ -56,6 +57,7 @@ func NewExecutor(ctx context.Context, db database.Store, ps pubsub.Pubsub, tss *
5657
tick: tick,
5758
log: log.Named("autobuild"),
5859
auditor: auditor,
60+
accessControlStore: acs,
5961
}
6062
return le
6163
}
@@ -159,6 +161,12 @@ func (e *Executor) runOnce(t time.Time) Stats {
159161
return nil
160162
}
161163

164+
template, err := tx.GetTemplateByID(e.ctx, ws.TemplateID)
165+
if err != nil {
166+
log.Warn(e.ctx, "get template by id", slog.Error(err))
167+
}
168+
accessControl := (*(e.accessControlStore.Load())).GetTemplateAccessControl(template)
169+
162170
latestJob, err := tx.GetProvisionerJobByID(e.ctx, latestBuild.JobID)
163171
if err != nil {
164172
log.Warn(e.ctx, "get last provisioner job for workspace %q: %w", slog.Error(err))
@@ -179,12 +187,13 @@ func (e *Executor) runOnce(t time.Time) Stats {
179187
Reason(reason)
180188
log.Debug(e.ctx, "auto building workspace", slog.F("transition", nextTransition))
181189
if nextTransition == database.WorkspaceTransitionStart &&
182-
ws.AutomaticUpdates == database.AutomaticUpdatesAlways {
190+
useActiveVersion(accessControl, ws) {
183191
log.Debug(e.ctx, "autostarting with active version")
184192
builder = builder.ActiveVersion()
185193
}
186194

187-
build, job, err = builder.Build(e.ctx, tx, nil)
195+
build, job, err = builder.Build(e.ctx, tx, nil, audit.WorkspaceBuildBaggage{IP: "127.0.0.1"})
196+
188197
if err != nil {
189198
log.Error(e.ctx, "unable to transition workspace",
190199
slog.F("transition", nextTransition),
@@ -469,3 +478,7 @@ func auditBuild(ctx context.Context, log slog.Logger, auditor audit.Auditor, par
469478
AdditionalFields: raw,
470479
})
471480
}
481+
482+
func useActiveVersion(opts dbauthz.TemplateAccessControl, ws database.Workspace) bool {
483+
return opts.RequireActiveVersion || ws.AutomaticUpdates == database.AutomaticUpdatesAlways
484+
}

0 commit comments

Comments
 (0)