Skip to content

Commit d6dd9e7

Browse files
committed
chore: Handle custom workspace proxy options. Remove excess
Add primary access url Include app security key Add output formats for registering a proxy Fix formats Add cli cmd to get app security key Add deleting proxies feat: Allow workspace proxy spawn in develop.sh Make gen Import ordeR Quote shell var Imports Fix lint Tabs vs spaces remove unused command Fix compile and make gen Fix slim cmd to include extra proxy cmds Import order Import order Fix comment Fix compile with name
1 parent b552283 commit d6dd9e7

21 files changed

+930
-359
lines changed

cli/clibase/option.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ func (s *OptionSet) Add(opts ...Option) {
8080
*s = append(*s, opts...)
8181
}
8282

83+
func (s OptionSet) Filter(filter func(opt Option) bool) OptionSet {
84+
cpy := make(OptionSet, 0)
85+
for _, opt := range s {
86+
if filter(opt) {
87+
cpy = append(cpy, opt)
88+
}
89+
}
90+
return cpy
91+
}
92+
8393
// FlagSet returns a pflag.FlagSet for the OptionSet.
8494
func (s *OptionSet) FlagSet() *pflag.FlagSet {
8595
if s == nil {

cli/cliui/output.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,30 @@ func (textFormat) AttachOptions(_ *clibase.OptionSet) {}
192192
func (textFormat) Format(_ context.Context, data any) (string, error) {
193193
return fmt.Sprintf("%s", data), nil
194194
}
195+
196+
type DataChangeFormat struct {
197+
format OutputFormat
198+
change func(data any) (any, error)
199+
}
200+
201+
// ChangeFormatterData allows manipulating the data passed to an output
202+
// format.
203+
func ChangeFormatterData(format OutputFormat, change func(data any) (any, error)) *DataChangeFormat {
204+
return &DataChangeFormat{format: format, change: change}
205+
}
206+
207+
func (d *DataChangeFormat) ID() string {
208+
return d.format.ID()
209+
}
210+
211+
func (d *DataChangeFormat) AttachOptions(opts *clibase.OptionSet) {
212+
d.format.AttachOptions(opts)
213+
}
214+
215+
func (d *DataChangeFormat) Format(ctx context.Context, data any) (string, error) {
216+
newData, err := d.change(data)
217+
if err != nil {
218+
return "", err
219+
}
220+
return d.format.Format(ctx, newData)
221+
}

cli/server.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,19 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
163163
var (
164164
cfg = new(codersdk.DeploymentValues)
165165
opts = cfg.Options()
166+
// For the develop.sh script, it is helpful to make this key deterministic.
167+
devAppSecurityKey string
168+
)
169+
opts.Add(
170+
clibase.Option{
171+
Name: "App Security Key (Development Only)",
172+
Description: "Used to override the app security key stored in the database. This should never be used in production.",
173+
Flag: "dangerous-dev-app-security-key",
174+
Default: "",
175+
Value: clibase.StringOf(&devAppSecurityKey),
176+
Annotations: clibase.Annotations{}.Mark("secret", "true"),
177+
Hidden: true,
178+
},
166179
)
167180
serverCmd := &clibase.Cmd{
168181
Use: "server",
@@ -621,6 +634,17 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
621634
}
622635
}
623636

637+
if devAppSecurityKey != "" {
638+
_, err := workspaceapps.KeyFromString(devAppSecurityKey)
639+
if err != nil {
640+
return xerrors.Errorf("invalid dev app security key: %w", err)
641+
}
642+
err = tx.UpsertAppSecurityKey(ctx, devAppSecurityKey)
643+
if err != nil {
644+
return xerrors.Errorf("Insert dev app security key: %w", err)
645+
}
646+
}
647+
624648
// Read the app signing key from the DB. We store it hex encoded
625649
// since the config table uses strings for the value and we
626650
// don't want to deal with automatic encoding issues.

coderd/apidoc/docs.go

Lines changed: 43 additions & 3 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: 37 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbauthz/querier.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,6 +1697,10 @@ func (q *querier) GetWorkspaceProxyByID(ctx context.Context, id uuid.UUID) (data
16971697
return fetch(q.log, q.auth, q.db.GetWorkspaceProxyByID)(ctx, id)
16981698
}
16991699

1700+
func (q *querier) GetWorkspaceProxyByName(ctx context.Context, name string) (database.WorkspaceProxy, error) {
1701+
return fetch(q.log, q.auth, q.db.GetWorkspaceProxyByName)(ctx, name)
1702+
}
1703+
17001704
func (q *querier) GetWorkspaceProxyByHostname(ctx context.Context, hostname string) (database.WorkspaceProxy, error) {
17011705
return fetch(q.log, q.auth, q.db.GetWorkspaceProxyByHostname)(ctx, hostname)
17021706
}

coderd/database/dbfake/databasefake.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5097,6 +5097,18 @@ func (q *fakeQuerier) GetWorkspaceProxyByID(_ context.Context, id uuid.UUID) (da
50975097
return database.WorkspaceProxy{}, sql.ErrNoRows
50985098
}
50995099

5100+
func (q *fakeQuerier) GetWorkspaceProxyByName(_ context.Context, name string) (database.WorkspaceProxy, error) {
5101+
q.mutex.Lock()
5102+
defer q.mutex.Unlock()
5103+
5104+
for _, proxy := range q.workspaceProxies {
5105+
if proxy.Name == name {
5106+
return proxy, nil
5107+
}
5108+
}
5109+
return database.WorkspaceProxy{}, sql.ErrNoRows
5110+
}
5111+
51005112
func (q *fakeQuerier) GetWorkspaceProxyByHostname(_ context.Context, hostname string) (database.WorkspaceProxy, error) {
51015113
q.mutex.Lock()
51025114
defer q.mutex.Unlock()

coderd/database/querier.go

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

coderd/database/queries.sql.go

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

coderd/database/queries/proxies.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ WHERE
4949
LIMIT
5050
1;
5151

52+
-- name: GetWorkspaceProxyByName :one
53+
SELECT
54+
*
55+
FROM
56+
workspace_proxies
57+
WHERE
58+
name = $1
59+
LIMIT
60+
1;
61+
5262
-- Finds a workspace proxy that has an access URL or app hostname that matches
5363
-- the provided hostname. This is to check if a hostname matches any workspace
5464
-- proxy.

coderd/httpmw/workspaceproxy.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"strings"
1010

11+
"github.com/go-chi/chi/v5"
1112
"github.com/google/uuid"
1213
"golang.org/x/xerrors"
1314

@@ -156,3 +157,53 @@ func ExtractWorkspaceProxy(opts ExtractWorkspaceProxyConfig) func(http.Handler)
156157
})
157158
}
158159
}
160+
161+
type workspaceProxyParamContextKey struct{}
162+
163+
// WorkspaceProxyParam returns the worksace proxy from the ExtractWorkspaceProxyParam handler.
164+
func WorkspaceProxyParam(r *http.Request) database.WorkspaceProxy {
165+
user, ok := r.Context().Value(workspaceProxyParamContextKey{}).(database.WorkspaceProxy)
166+
if !ok {
167+
panic("developer error: workspace proxy parameter middleware not provided")
168+
}
169+
return user
170+
}
171+
172+
// ExtractWorkspaceProxyParam extracts a workspace proxy from an ID/name in the {workspaceproxy} URL
173+
// parameter.
174+
//
175+
//nolint:revive
176+
func ExtractWorkspaceProxyParam(db database.Store) func(http.Handler) http.Handler {
177+
return func(next http.Handler) http.Handler {
178+
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
179+
ctx := r.Context()
180+
181+
proxyQuery := chi.URLParam(r, "workspaceproxy")
182+
if proxyQuery == "" {
183+
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
184+
Message: "\"workspaceproxy\" must be provided.",
185+
})
186+
return
187+
}
188+
189+
var proxy database.WorkspaceProxy
190+
var dbErr error
191+
if proxyID, err := uuid.Parse(proxyQuery); err == nil {
192+
proxy, dbErr = db.GetWorkspaceProxyByID(ctx, proxyID)
193+
} else {
194+
proxy, dbErr = db.GetWorkspaceProxyByName(ctx, proxyQuery)
195+
}
196+
if httpapi.Is404Error(dbErr) {
197+
httpapi.ResourceNotFound(rw)
198+
return
199+
}
200+
if dbErr != nil {
201+
httpapi.InternalServerError(rw, dbErr)
202+
return
203+
}
204+
205+
ctx = context.WithValue(ctx, workspaceProxyParamContextKey{}, proxy)
206+
next.ServeHTTP(rw, r.WithContext(ctx))
207+
})
208+
}
209+
}

0 commit comments

Comments
 (0)