Skip to content

Commit 2242db6

Browse files
authored
Merge pull request #21 from stacklok/feat/userns-support
Enable user namespace for runner to fix virtiofs EPERM
2 parents 48436c4 + 4dd6045 commit 2242db6

10 files changed

Lines changed: 50 additions & 143 deletions

File tree

.github/workflows/build.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ on:
99
permissions:
1010
contents: read
1111

12+
env:
13+
GOPRIVATE: github.com/stacklok/*
14+
1215
jobs:
1316
build:
1417
name: Build and Test
@@ -23,6 +26,10 @@ jobs:
2326
go-version-file: 'go.mod'
2427
cache: true
2528

29+
- name: Configure Git for private modules
30+
run: |
31+
git config --global url."https://${{ github.actor }}:${{ secrets.GO_MODULE_TOKEN }}@github.com/".insteadOf "https://github.com/"
32+
2633
- name: Install Task
2734
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
2835
with:

.github/workflows/lint.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ on:
99
permissions:
1010
contents: read
1111

12+
env:
13+
GOPRIVATE: github.com/stacklok/*
14+
1215
jobs:
1316
lint:
1417
name: Lint
@@ -22,6 +25,10 @@ jobs:
2225
go-version-file: 'go.mod'
2326
cache: true
2427

28+
- name: Configure Git for private modules
29+
run: |
30+
git config --global url."https://${{ github.actor }}:${{ secrets.GO_MODULE_TOKEN }}@github.com/".insteadOf "https://github.com/"
31+
2532
- name: Install Task
2633
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
2734
with:

.github/workflows/release.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ on:
1010

1111
permissions: {}
1212

13+
env:
14+
GOPRIVATE: github.com/stacklok/*
15+
1316
jobs:
1417
release:
1518
name: Release Container
@@ -24,19 +27,16 @@ jobs:
2427
with:
2528
fetch-depth: 0
2629

27-
- name: Checkout propolis (sibling dependency)
28-
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
29-
with:
30-
repository: stacklok/propolis
31-
ref: 6a81046b0472c54c877b965c34c97c094f373d74 # v0.1.0
32-
path: ../propolis
33-
3430
- name: Set up Go
3531
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
3632
with:
3733
go-version-file: 'go.mod'
3834
cache: true
3935

36+
- name: Configure Git for private modules
37+
run: |
38+
git config --global url."https://${{ github.actor }}:${{ secrets.GO_MODULE_TOKEN }}@github.com/".insteadOf "https://github.com/"
39+
4040
- name: Install Task
4141
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
4242
with:

.github/workflows/run-on-main.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ jobs:
1515
linting:
1616
name: Linting
1717
uses: ./.github/workflows/lint.yml
18+
secrets: inherit
1819
tests:
1920
name: Tests
2021
uses: ./.github/workflows/test.yml
22+
secrets: inherit
2123
build:
2224
name: Build
2325
uses: ./.github/workflows/build.yml
26+
secrets: inherit

.github/workflows/run-on-pr.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ jobs:
1414
linting:
1515
name: Linting
1616
uses: ./.github/workflows/lint.yml
17+
secrets: inherit
1718
tests:
1819
name: Tests
1920
uses: ./.github/workflows/test.yml
21+
secrets: inherit

.github/workflows/test.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ on:
99
permissions:
1010
contents: read
1111

12+
env:
13+
GOPRIVATE: github.com/stacklok/*
14+
1215
jobs:
1316
test:
1417
name: Test
@@ -22,6 +25,10 @@ jobs:
2225
go-version-file: 'go.mod'
2326
cache: true
2427

28+
- name: Configure Git for private modules
29+
run: |
30+
git config --global url."https://${{ github.actor }}:${{ secrets.GO_MODULE_TOKEN }}@github.com/".insteadOf "https://github.com/"
31+
2532
- name: Install Task
2633
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
2734
with:

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/adrg/xdg v0.5.3
1010
github.com/google/uuid v1.6.0
1111
github.com/mark3labs/mcp-go v0.44.0
12-
github.com/stacklok/propolis v0.0.16
12+
github.com/stacklok/propolis v0.0.18
1313
)
1414

1515
require (
@@ -63,9 +63,9 @@ require (
6363
go.opentelemetry.io/otel v1.40.0 // indirect
6464
go.opentelemetry.io/otel/metric v1.40.0 // indirect
6565
go.opentelemetry.io/otel/trace v1.40.0 // indirect
66-
golang.org/x/crypto v0.48.0 // indirect
66+
golang.org/x/crypto v0.49.0 // indirect
6767
golang.org/x/mod v0.33.0 // indirect
68-
golang.org/x/net v0.50.0 // indirect
68+
golang.org/x/net v0.51.0 // indirect
6969
golang.org/x/sync v0.20.0 // indirect
7070
golang.org/x/sys v0.42.0 // indirect
7171
golang.org/x/time v0.5.0 // indirect

go.sum

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w
130130
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
131131
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
132132
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
133-
github.com/stacklok/propolis v0.0.16 h1:dC/knkrY7e6XpsWxmxtxBnAgRw+Lvbw4TJyM9lMYjOM=
134-
github.com/stacklok/propolis v0.0.16/go.mod h1:f0k7aMlo4EC6BhFMWasYs/RJTHc2Qb37bZu5GJvuJU0=
133+
github.com/stacklok/propolis v0.0.18 h1:WzAqNAg2sSd7q6bJZUfEMilkzy8q/R7Ii7VtlM29dAE=
134+
github.com/stacklok/propolis v0.0.18/go.mod h1:C727m7ggN78TJ0vok+68e+YKnZMlm1L4GlY63P4IReA=
135135
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
136136
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
137137
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
@@ -170,16 +170,16 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
170170
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
171171
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
172172
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
173-
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
174-
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
173+
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
174+
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
175175
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
176176
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
177177
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
178178
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
179179
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
180180
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
181-
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
182-
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
181+
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
182+
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
183183
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
184184
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
185185
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
@@ -189,11 +189,11 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
189189
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
190190
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
191191
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
192-
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
193-
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
192+
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
193+
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
194194
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
195-
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
196-
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
195+
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
196+
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
197197
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
198198
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
199199
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=

pkg/infra/vm/propolis.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ func (p *PropolisProvider) buildBackendOpts(opts CreateVMOpts) []libkrun.Option
256256
if runtimeSrc != nil || firmwareSrc != nil {
257257
out = append(out, libkrun.WithCacheDir(cacheDir))
258258
}
259+
// Spawn the runner in a user namespace so libkrun's virtiofs passthrough
260+
// gains CAP_SETGID within the namespace. Without this, set_creds() fails
261+
// with EPERM when host GID != guest GID.
262+
out = append(out, libkrun.WithUserNamespaceUID(1000, 1000))
259263
return out
260264
}
261265

pkg/infra/vm/propolis_test.go

Lines changed: 0 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -63,129 +63,6 @@ func TestNewPropolisProvider(t *testing.T) {
6363
})
6464
}
6565

66-
// TestBuildBackendOpts verifies the merging logic in buildBackendOpts.
67-
// Since libkrun.Option is an opaque func type, we assert on option count
68-
// to verify which branches were taken. Each configuration produces a
69-
// unique count.
70-
func TestBuildBackendOpts(t *testing.T) {
71-
t.Parallel()
72-
73-
rtSrc := extract.Dir(t.TempDir())
74-
fwSrc := extract.Dir(t.TempDir())
75-
altSrc := extract.Dir(t.TempDir())
76-
77-
tests := []struct {
78-
name string
79-
provider *PropolisProvider
80-
opts CreateVMOpts
81-
wantCount int
82-
}{
83-
{
84-
name: "no sources no paths",
85-
provider: NewPropolisProvider(),
86-
opts: CreateVMOpts{DataDir: "/tmp"},
87-
wantCount: 0,
88-
},
89-
{
90-
name: "runner path only",
91-
provider: NewPropolisProvider(),
92-
opts: CreateVMOpts{
93-
RunnerPath: "/usr/bin/propolis-runner",
94-
DataDir: "/tmp",
95-
},
96-
wantCount: 1,
97-
},
98-
{
99-
name: "runner path and lib dir",
100-
provider: NewPropolisProvider(),
101-
opts: CreateVMOpts{
102-
RunnerPath: "/usr/bin/propolis-runner",
103-
LibDir: "/usr/lib",
104-
DataDir: "/tmp",
105-
},
106-
wantCount: 2,
107-
},
108-
{
109-
name: "provider runtime source only",
110-
provider: NewPropolisProvider(WithRuntimeSource(rtSrc)),
111-
opts: CreateVMOpts{DataDir: "/tmp"},
112-
// WithRuntime + WithCacheDir = 2
113-
wantCount: 2,
114-
},
115-
{
116-
name: "provider firmware source only",
117-
provider: NewPropolisProvider(WithFirmwareSource(fwSrc)),
118-
opts: CreateVMOpts{DataDir: "/tmp"},
119-
// WithFirmware + WithCacheDir = 2
120-
wantCount: 2,
121-
},
122-
{
123-
name: "provider both sources",
124-
provider: NewPropolisProvider(
125-
WithRuntimeSource(rtSrc),
126-
WithFirmwareSource(fwSrc),
127-
),
128-
opts: CreateVMOpts{DataDir: "/tmp"},
129-
// WithRuntime + WithFirmware + WithCacheDir = 3
130-
wantCount: 3,
131-
},
132-
{
133-
name: "runtime source suppresses runner path and lib dir",
134-
provider: NewPropolisProvider(WithRuntimeSource(rtSrc)),
135-
opts: CreateVMOpts{
136-
RunnerPath: "/usr/bin/propolis-runner",
137-
LibDir: "/usr/lib",
138-
DataDir: "/tmp",
139-
},
140-
// WithRuntime + WithCacheDir = 2 (RunnerPath/LibDir ignored)
141-
wantCount: 2,
142-
},
143-
{
144-
name: "per-call runtime source overrides provider",
145-
provider: NewPropolisProvider(WithRuntimeSource(rtSrc)),
146-
opts: CreateVMOpts{
147-
RuntimeSource: altSrc,
148-
DataDir: "/tmp",
149-
},
150-
// WithRuntime(altSrc) + WithCacheDir = 2
151-
wantCount: 2,
152-
},
153-
{
154-
name: "per-call firmware source overrides provider",
155-
provider: NewPropolisProvider(WithFirmwareSource(fwSrc)),
156-
opts: CreateVMOpts{
157-
FirmwareSource: altSrc,
158-
DataDir: "/tmp",
159-
},
160-
// WithFirmware(altSrc) + WithCacheDir = 2
161-
wantCount: 2,
162-
},
163-
{
164-
name: "explicit cache dir used over data dir",
165-
provider: NewPropolisProvider(
166-
WithRuntimeSource(rtSrc),
167-
WithFirmwareSource(fwSrc),
168-
),
169-
opts: CreateVMOpts{
170-
DataDir: "/tmp/data",
171-
CacheDir: "/tmp/cache",
172-
},
173-
// WithRuntime + WithFirmware + WithCacheDir = 3
174-
wantCount: 3,
175-
},
176-
}
177-
178-
for _, tt := range tests {
179-
t.Run(tt.name, func(t *testing.T) {
180-
t.Parallel()
181-
got := tt.provider.buildBackendOpts(tt.opts)
182-
if len(got) != tt.wantCount {
183-
t.Errorf("buildBackendOpts returned %d options, want %d", len(got), tt.wantCount)
184-
}
185-
})
186-
}
187-
}
188-
18966
func TestInitInjector(t *testing.T) {
19067
t.Parallel()
19168

0 commit comments

Comments
 (0)