Skip to content

Commit 63df928

Browse files
mishushakovclaude
andauthored
Configure FUSE for non-root user access (#1849)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent 4b1801c commit 63df928

3 files changed

Lines changed: 84 additions & 0 deletions

File tree

packages/orchestrator/pkg/template/build/phases/base/provision.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ else
3838
echo "All required packages are already installed."
3939
fi
4040

41+
# Set /dev/fuse permissions to 666 for non-root access
42+
# Use systemd-tmpfiles to set permissions at boot
43+
mkdir -p /etc/tmpfiles.d
44+
echo 'z /dev/fuse 0666 root root -' > /etc/tmpfiles.d/fuse.conf
45+
4146
echo "Setting up shell"
4247
echo "export SHELL='/bin/bash'" >/etc/profile.d/shell.sh
4348
echo "export PS1='\w \$ '" >/etc/profile.d/prompt.sh
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package sandboxes
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/e2b-dev/infra/tests/integration/internal/setup"
11+
"github.com/e2b-dev/infra/tests/integration/internal/utils"
12+
)
13+
14+
func TestFuseDevicePermissions(t *testing.T) {
15+
t.Parallel()
16+
ctx := t.Context()
17+
18+
client := setup.GetAPIClient()
19+
sbx := utils.SetupSandboxWithCleanup(t, client)
20+
21+
envdClient := setup.GetEnvdClient(t, ctx)
22+
23+
// Log detailed /dev/fuse info for debugging
24+
lsOutput, _ := utils.ExecCommandAsRootWithOutput(t, ctx, sbx, envdClient, "ls", "-la", "/dev/fuse")
25+
t.Logf("/dev/fuse listing: %s", strings.TrimSpace(lsOutput))
26+
27+
// Check /dev/fuse permissions - should be 0666 (crw-rw-rw-)
28+
output, err := utils.ExecCommandAsRootWithOutput(t, ctx, sbx, envdClient, "stat", "-c", "%a", "/dev/fuse")
29+
require.NoError(t, err, "Failed to stat /dev/fuse")
30+
t.Logf("/dev/fuse permissions: %s", strings.TrimSpace(output))
31+
assert.Equal(t, "666", strings.TrimSpace(output), "Expected /dev/fuse to have permissions 666")
32+
}
33+
34+
func TestFuseNonRootAccess(t *testing.T) {
35+
t.Parallel()
36+
ctx := t.Context()
37+
38+
client := setup.GetAPIClient()
39+
sbx := utils.SetupSandboxWithCleanup(t, client)
40+
41+
envdClient := setup.GetEnvdClient(t, ctx)
42+
43+
// Test that non-root user can open /dev/fuse for reading
44+
// This verifies the device permissions are set correctly
45+
err := utils.ExecCommand(t, ctx, sbx, envdClient, "test", "-r", "/dev/fuse")
46+
require.NoError(t, err, "Non-root user should be able to read /dev/fuse")
47+
48+
// Test that non-root user can open /dev/fuse for writing
49+
err = utils.ExecCommand(t, ctx, sbx, envdClient, "test", "-w", "/dev/fuse")
50+
require.NoError(t, err, "Non-root user should be able to write to /dev/fuse")
51+
}

tests/integration/internal/tests/api/templates/build_template_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,3 +1157,31 @@ func TestTemplateBuildCOPY(t *testing.T) {
11571157
},
11581158
))
11591159
}
1160+
1161+
func TestTemplateBuildFuseConfiguration(t *testing.T) {
1162+
t.Parallel()
1163+
1164+
// Test that FUSE is configured to allow non-root users:
1165+
// - /etc/tmpfiles.d/fuse.conf sets /dev/fuse permissions at boot
1166+
// - /dev/fuse has actual permissions 666
1167+
buildConfig := api.TemplateBuildStartV2{
1168+
Force: utils.ToPtr(ForceBaseBuild),
1169+
FromImage: utils.ToPtr("ubuntu:22.04"),
1170+
Steps: utils.ToPtr([]api.TemplateStep{
1171+
{
1172+
Type: "RUN",
1173+
Args: utils.ToPtr([]string{
1174+
"grep -q 'z /dev/fuse 0666 root root -' /etc/tmpfiles.d/fuse.conf",
1175+
}),
1176+
},
1177+
{
1178+
Type: "RUN",
1179+
Args: utils.ToPtr([]string{
1180+
"echo \"Checking /dev/fuse permissions:\"; ls -la /dev/fuse; stat -c 'mode=%a owner=%U group=%G' /dev/fuse; test $(stat -c %a /dev/fuse) = '666'",
1181+
}),
1182+
},
1183+
}),
1184+
}
1185+
1186+
assert.True(t, buildTemplate(t, "test-ubuntu-fuse-config", buildConfig, defaultBuildLogHandler(t)))
1187+
}

0 commit comments

Comments
 (0)