Skip to content

Commit 3861a43

Browse files
committed
Merge remote-tracking branch 'origin/main' into authzquerier_layer
2 parents 69d1aa3 + f24547e commit 3861a43

File tree

108 files changed

+3510
-650
lines changed

Some content is hidden

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

108 files changed

+3510
-650
lines changed

.github/workflows/security.yaml

+41-1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ jobs:
9292
restore-keys: |
9393
js-${{ runner.os }}-
9494
95+
- name: Install yq
96+
run: go run github.com/mikefarah/yq/v4@v4.30.6
97+
9598
- name: Build Coder linux amd64 Docker image
9699
id: build
97100
run: |
@@ -112,6 +115,17 @@ jobs:
112115
make -j "$image_job"
113116
echo "image=$(cat "$image_job")" >> $GITHUB_OUTPUT
114117
118+
- name: Build Coder linux amd64 Docker image (ironbank)
119+
id: build-ironbank
120+
run: |
121+
set -euo pipefail
122+
# NOTE: This is not a real image tag we publish.
123+
image_tag="${{ steps.build.outputs.image }}-ironbank"
124+
./scripts/ironbank/build_ironbank.sh \
125+
--target "$image_tag" \
126+
"build/coder_$(./scripts/version.sh)_linux_amd64"
127+
echo "image=$image_tag" >> $GITHUB_OUTPUT
128+
115129
- name: Run Trivy vulnerability scanner
116130
uses: aquasecurity/trivy-action@9ab158e8597f3b310480b9a69402b419bc03dbd5
117131
with:
@@ -124,10 +138,36 @@ jobs:
124138
uses: github/codeql-action/upload-sarif@v2
125139
with:
126140
sarif_file: trivy-results.sarif
141+
category: "Trivy"
142+
143+
- name: Run Trivy vulnerability scanner (ironbank)
144+
uses: aquasecurity/trivy-action@7b7aa264d83dc58691451798b4d117d53d21edfe
145+
with:
146+
image-ref: ${{ steps.build-ironbank.outputs.image }}
147+
format: sarif
148+
output: trivy-results-ironbank.sarif
149+
severity: "CRITICAL,HIGH"
150+
151+
# Update the tool name field in the ironbank SARIF file so it's not
152+
# indistinguishable from findings in the non-ironbank SARIF file in the
153+
# GitHub UI. Without this, findings from both scans would show up as
154+
# "Trivy".
155+
- name: Update tool name in SARIF file (ironbank)
156+
run: |
157+
set -euo pipefail
158+
yq eval -i '.runs[0].tool.driver.name = "Trivy Ironbank"' trivy-results-ironbank.sarif
159+
160+
- name: Upload Trivy scan results to GitHub Security tab (ironbank)
161+
uses: github/codeql-action/upload-sarif@v2
162+
with:
163+
sarif_file: trivy-results-ironbank.sarif
164+
category: "Trivy Ironbank"
127165

128166
- name: Upload Trivy scan results as an artifact
129167
uses: actions/upload-artifact@v2
130168
with:
131169
name: trivy
132-
path: trivy-results.sarif
170+
path: |
171+
trivy-results.sarif
172+
trivy-results-ironbank.sarif
133173
retention-days: 7

agent/agent.go

+41-7
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ type Client interface {
7575
ReportStats(ctx context.Context, log slog.Logger, stats func() *agentsdk.Stats) (io.Closer, error)
7676
PostLifecycle(ctx context.Context, state agentsdk.PostLifecycleRequest) error
7777
PostAppHealth(ctx context.Context, req agentsdk.PostAppHealthsRequest) error
78-
PostVersion(ctx context.Context, version string) error
78+
PostStartup(ctx context.Context, req agentsdk.PostStartupRequest) error
7979
}
8080

8181
func New(options Options) io.Closer {
@@ -236,16 +236,29 @@ func (a *agent) run(ctx context.Context) error {
236236
}
237237
a.sessionToken.Store(&sessionToken)
238238

239-
err = a.client.PostVersion(ctx, buildinfo.Version())
240-
if err != nil {
241-
return xerrors.Errorf("update workspace agent version: %w", err)
242-
}
243-
244239
metadata, err := a.client.Metadata(ctx)
245240
if err != nil {
246241
return xerrors.Errorf("fetch metadata: %w", err)
247242
}
248243
a.logger.Info(ctx, "fetched metadata")
244+
245+
// Expand the directory and send it back to coderd so external
246+
// applications that rely on the directory can use it.
247+
//
248+
// An example is VS Code Remote, which must know the directory
249+
// before initializing a connection.
250+
metadata.Directory, err = expandDirectory(metadata.Directory)
251+
if err != nil {
252+
return xerrors.Errorf("expand directory: %w", err)
253+
}
254+
err = a.client.PostStartup(ctx, agentsdk.PostStartupRequest{
255+
Version: buildinfo.Version(),
256+
ExpandedDirectory: metadata.Directory,
257+
})
258+
if err != nil {
259+
return xerrors.Errorf("update workspace agent version: %w", err)
260+
}
261+
249262
oldMetadata := a.metadata.Swap(metadata)
250263

251264
// The startup script should only execute on the first run!
@@ -803,7 +816,11 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri
803816

804817
cmd := exec.CommandContext(ctx, shell, args...)
805818
cmd.Dir = metadata.Directory
806-
if cmd.Dir == "" {
819+
820+
// If the metadata directory doesn't exist, we run the command
821+
// in the users home directory.
822+
_, err = os.Stat(cmd.Dir)
823+
if cmd.Dir == "" || err != nil {
807824
// Default to user home if a directory is not set.
808825
homedir, err := userHomeDir()
809826
if err != nil {
@@ -1314,3 +1331,20 @@ func userHomeDir() (string, error) {
13141331
}
13151332
return u.HomeDir, nil
13161333
}
1334+
1335+
// expandDirectory converts a directory path to an absolute path.
1336+
// It primarily resolves the home directory and any environment
1337+
// variables that may be set
1338+
func expandDirectory(dir string) (string, error) {
1339+
if dir == "" {
1340+
return "", nil
1341+
}
1342+
if dir[0] == '~' {
1343+
home, err := userHomeDir()
1344+
if err != nil {
1345+
return "", err
1346+
}
1347+
dir = filepath.Join(home, dir[1:])
1348+
}
1349+
return os.ExpandEnv(dir), nil
1350+
}

agent/agent_test.go

+61-1
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,56 @@ func TestAgent_Lifecycle(t *testing.T) {
787787
})
788788
}
789789

790+
func TestAgent_Startup(t *testing.T) {
791+
t.Parallel()
792+
793+
t.Run("EmptyDirectory", func(t *testing.T) {
794+
t.Parallel()
795+
796+
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
797+
StartupScript: "true",
798+
StartupScriptTimeout: 30 * time.Second,
799+
Directory: "",
800+
}, 0)
801+
assert.Eventually(t, func() bool {
802+
return client.getStartup().Version != ""
803+
}, testutil.WaitShort, testutil.IntervalFast)
804+
require.Equal(t, "", client.getStartup().ExpandedDirectory)
805+
})
806+
807+
t.Run("HomeDirectory", func(t *testing.T) {
808+
t.Parallel()
809+
810+
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
811+
StartupScript: "true",
812+
StartupScriptTimeout: 30 * time.Second,
813+
Directory: "~",
814+
}, 0)
815+
assert.Eventually(t, func() bool {
816+
return client.getStartup().Version != ""
817+
}, testutil.WaitShort, testutil.IntervalFast)
818+
homeDir, err := os.UserHomeDir()
819+
require.NoError(t, err)
820+
require.Equal(t, homeDir, client.getStartup().ExpandedDirectory)
821+
})
822+
823+
t.Run("HomeEnvironmentVariable", func(t *testing.T) {
824+
t.Parallel()
825+
826+
_, client, _, _ := setupAgent(t, agentsdk.Metadata{
827+
StartupScript: "true",
828+
StartupScriptTimeout: 30 * time.Second,
829+
Directory: "$HOME",
830+
}, 0)
831+
assert.Eventually(t, func() bool {
832+
return client.getStartup().Version != ""
833+
}, testutil.WaitShort, testutil.IntervalFast)
834+
homeDir, err := os.UserHomeDir()
835+
require.NoError(t, err)
836+
require.Equal(t, homeDir, client.getStartup().ExpandedDirectory)
837+
})
838+
}
839+
790840
func TestAgent_ReconnectingPTY(t *testing.T) {
791841
t.Parallel()
792842
if runtime.GOOS == "windows" {
@@ -1178,6 +1228,7 @@ type client struct {
11781228

11791229
mu sync.Mutex // Protects following.
11801230
lifecycleStates []codersdk.WorkspaceAgentLifecycle
1231+
startup agentsdk.PostStartupRequest
11811232
}
11821233

11831234
func (c *client) Metadata(_ context.Context) (agentsdk.Metadata, error) {
@@ -1250,7 +1301,16 @@ func (*client) PostAppHealth(_ context.Context, _ agentsdk.PostAppHealthsRequest
12501301
return nil
12511302
}
12521303

1253-
func (*client) PostVersion(_ context.Context, _ string) error {
1304+
func (c *client) getStartup() agentsdk.PostStartupRequest {
1305+
c.mu.Lock()
1306+
defer c.mu.Unlock()
1307+
return c.startup
1308+
}
1309+
1310+
func (c *client) PostStartup(_ context.Context, startup agentsdk.PostStartupRequest) error {
1311+
c.mu.Lock()
1312+
defer c.mu.Unlock()
1313+
c.startup = startup
12541314
return nil
12551315
}
12561316

cli/cliui/parameter.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,5 @@ func validateRichPrompt(value string, p codersdk.TemplateVersionParameter) error
114114
return codersdk.ValidateWorkspaceBuildParameter(p, codersdk.WorkspaceBuildParameter{
115115
Name: p.Name,
116116
Value: value,
117-
})
117+
}, nil)
118118
}

cli/create_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func TestCreate(t *testing.T) {
8787
_ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
8888
cmd, root := clitest.New(t, "create", "my-workspace", "-y")
8989

90-
member := coderdtest.CreateAnotherUser(t, client, user.OrganizationID)
90+
member, _ := coderdtest.CreateAnotherUser(t, client, user.OrganizationID)
9191
clitest.SetupConfig(t, member, root)
9292
cmdCtx, done := context.WithTimeout(context.Background(), testutil.WaitLong)
9393
go func() {

cli/delete_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func TestDelete(t *testing.T) {
7777
adminClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
7878
adminUser := coderdtest.CreateFirstUser(t, adminClient)
7979
orgID := adminUser.OrganizationID
80-
client := coderdtest.CreateAnotherUser(t, adminClient, orgID)
80+
client, _ := coderdtest.CreateAnotherUser(t, adminClient, orgID)
8181
user, err := client.User(context.Background(), codersdk.Me)
8282
require.NoError(t, err)
8383

cli/userlist_test.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,9 @@ func TestUserShow(t *testing.T) {
8787

8888
t.Run("Table", func(t *testing.T) {
8989
t.Parallel()
90-
ctx := context.Background()
9190
client := coderdtest.New(t, nil)
9291
admin := coderdtest.CreateFirstUser(t, client)
93-
other := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
94-
otherUser, err := other.User(ctx, codersdk.Me)
95-
require.NoError(t, err, "fetch other user")
92+
_, otherUser := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
9693
cmd, root := clitest.New(t, "users", "show", otherUser.Username)
9794
clitest.SetupConfig(t, client, root)
9895
doneChan := make(chan struct{})
@@ -114,7 +111,7 @@ func TestUserShow(t *testing.T) {
114111
ctx := context.Background()
115112
client := coderdtest.New(t, nil)
116113
admin := coderdtest.CreateFirstUser(t, client)
117-
other := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
114+
other, _ := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
118115
otherUser, err := other.User(ctx, codersdk.Me)
119116
require.NoError(t, err, "fetch other user")
120117
cmd, root := clitest.New(t, "users", "show", otherUser.Username, "-o", "json")

cli/userstatus_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func TestUserStatus(t *testing.T) {
1717
t.Parallel()
1818
client := coderdtest.New(t, nil)
1919
admin := coderdtest.CreateFirstUser(t, client)
20-
other := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
20+
other, _ := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
2121
otherUser, err := other.User(context.Background(), codersdk.Me)
2222
require.NoError(t, err, "fetch user")
2323

0 commit comments

Comments
 (0)