Skip to content

Commit 92cc595

Browse files
committed
llbsolver: make sure interactive container API validates entitlements
Ensure interactive calls validate same conditions that the build requests do. Refactor of the build side is to ensure we use the same validation function for both cases. There was no validation issue with the LLB validation. Signed-off-by: Tonis Tiigi <[email protected]> (cherry picked from commit d1970522d7145be5f4a1f1a028b1910bb527126c) (cherry picked from commit e1e30278d0a491dfd34bd80fa66b54106614cffa)
1 parent 5026d95 commit 92cc595

File tree

4 files changed

+97
-16
lines changed

4 files changed

+97
-16
lines changed

client/build_test.go

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ func TestClientGatewayIntegration(t *testing.T) {
6262
), integration.WithMirroredImages(integration.OfficialImages("busybox:latest")))
6363

6464
integration.Run(t, integration.TestFuncs(
65-
testClientGatewayContainerSecurityMode,
65+
testClientGatewayContainerSecurityModeCaps,
66+
testClientGatewayContainerSecurityModeValidation,
6667
), integration.WithMirroredImages(integration.OfficialImages("busybox:latest")),
6768
integration.WithMatrix("secmode", map[string]interface{}{
6869
"sandbox": securitySandbox,
@@ -71,7 +72,8 @@ func TestClientGatewayIntegration(t *testing.T) {
7172
)
7273

7374
integration.Run(t, integration.TestFuncs(
74-
testClientGatewayContainerHostNetworking,
75+
testClientGatewayContainerHostNetworkingAccess,
76+
testClientGatewayContainerHostNetworkingValidation,
7577
),
7678
integration.WithMirroredImages(integration.OfficialImages("busybox:latest")),
7779
integration.WithMatrix("netmode", map[string]interface{}{
@@ -1836,9 +1838,17 @@ func testClientGatewayExecFileActionError(t *testing.T, sb integration.Sandbox)
18361838
checkAllReleasable(t, c, sb, true)
18371839
}
18381840

1839-
// testClientGatewayContainerSecurityMode ensures that the correct security mode
1841+
// testClientGatewayContainerSecurityModeCaps ensures that the correct security mode
18401842
// is propagated to the gateway container
1841-
func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox) {
1843+
func testClientGatewayContainerSecurityModeCaps(t *testing.T, sb integration.Sandbox) {
1844+
testClientGatewayContainerSecurityMode(t, sb, false)
1845+
}
1846+
1847+
func testClientGatewayContainerSecurityModeValidation(t *testing.T, sb integration.Sandbox) {
1848+
testClientGatewayContainerSecurityMode(t, sb, true)
1849+
}
1850+
1851+
func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox, expectFail bool) {
18421852
integration.CheckFeatureCompat(t, sb, integration.FeatureSecurityMode)
18431853
requiresLinux(t)
18441854

@@ -1865,6 +1875,9 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox
18651875
require.EqualValues(t, 0xa80425fb, caps)
18661876
}
18671877
allowedEntitlements = []entitlements.Entitlement{}
1878+
if expectFail {
1879+
return
1880+
}
18681881
} else {
18691882
assertCaps = func(caps uint64) {
18701883
/*
@@ -1881,6 +1894,9 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox
18811894
}
18821895
mode = llb.SecurityModeInsecure
18831896
allowedEntitlements = []entitlements.Entitlement{entitlements.EntitlementSecurityInsecure}
1897+
if expectFail {
1898+
allowedEntitlements = []entitlements.Entitlement{}
1899+
}
18841900
}
18851901

18861902
b := func(ctx context.Context, c client.Client) (*client.Result, error) {
@@ -1930,6 +1946,12 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox
19301946
t.Logf("Stdout: %q", stdout.String())
19311947
t.Logf("Stderr: %q", stderr.String())
19321948

1949+
if expectFail {
1950+
require.Error(t, err)
1951+
require.Contains(t, err.Error(), "security.insecure is not allowed")
1952+
return nil, err
1953+
}
1954+
19331955
require.NoError(t, err)
19341956

19351957
capsValue, err := strconv.ParseUint(strings.TrimSpace(stdout.String()), 16, 64)
@@ -1944,7 +1966,13 @@ func testClientGatewayContainerSecurityMode(t *testing.T, sb integration.Sandbox
19441966
AllowedEntitlements: allowedEntitlements,
19451967
}
19461968
_, err = c.Build(ctx, solveOpts, product, b, nil)
1947-
require.NoError(t, err)
1969+
1970+
if expectFail {
1971+
require.Error(t, err)
1972+
require.Contains(t, err.Error(), "security.insecure is not allowed")
1973+
} else {
1974+
require.NoError(t, err)
1975+
}
19481976

19491977
checkAllReleasable(t, c, sb, true)
19501978
}
@@ -2020,7 +2048,15 @@ func testClientGatewayContainerExtraHosts(t *testing.T, sb integration.Sandbox)
20202048
checkAllReleasable(t, c, sb, true)
20212049
}
20222050

2023-
func testClientGatewayContainerHostNetworking(t *testing.T, sb integration.Sandbox) {
2051+
func testClientGatewayContainerHostNetworkingAccess(t *testing.T, sb integration.Sandbox) {
2052+
testClientGatewayContainerHostNetworking(t, sb, false)
2053+
}
2054+
2055+
func testClientGatewayContainerHostNetworkingValidation(t *testing.T, sb integration.Sandbox) {
2056+
testClientGatewayContainerHostNetworking(t, sb, true)
2057+
}
2058+
2059+
func testClientGatewayContainerHostNetworking(t *testing.T, sb integration.Sandbox, expectFail bool) {
20242060
if os.Getenv("BUILDKIT_RUN_NETWORK_INTEGRATION_TESTS") == "" {
20252061
t.SkipNow()
20262062
}
@@ -2041,6 +2077,9 @@ func testClientGatewayContainerHostNetworking(t *testing.T, sb integration.Sandb
20412077
if sb.Value("netmode") == hostNetwork {
20422078
netMode = pb.NetMode_HOST
20432079
allowedEntitlements = []entitlements.Entitlement{entitlements.EntitlementNetworkHost}
2080+
if expectFail {
2081+
allowedEntitlements = []entitlements.Entitlement{}
2082+
}
20442083
}
20452084
c, err := New(sb.Context(), sb.Address())
20462085
require.NoError(t, err)
@@ -2099,7 +2138,12 @@ func testClientGatewayContainerHostNetworking(t *testing.T, sb integration.Sandb
20992138
t.Logf("Stderr: %q", stderr.String())
21002139

21012140
if netMode == pb.NetMode_HOST {
2102-
require.NoError(t, err)
2141+
if expectFail {
2142+
require.Error(t, err)
2143+
require.Contains(t, err.Error(), "network.host is not allowed")
2144+
} else {
2145+
require.NoError(t, err)
2146+
}
21032147
} else {
21042148
require.Error(t, err)
21052149
}

solver/llbsolver/bridge.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/moby/buildkit/sourcepolicy"
2626
spb "github.com/moby/buildkit/sourcepolicy/pb"
2727
"github.com/moby/buildkit/util/bklog"
28+
"github.com/moby/buildkit/util/entitlements"
2829
"github.com/moby/buildkit/util/flightcontrol"
2930
"github.com/moby/buildkit/util/progress"
3031
"github.com/moby/buildkit/worker"
@@ -165,14 +166,34 @@ func (b *llbBridge) loadResult(ctx context.Context, def *pb.Definition, cacheImp
165166
return res, nil
166167
}
167168

169+
func (b *llbBridge) validateEntitlements(p executor.ProcessInfo) error {
170+
ent, err := loadEntitlements(b.builder)
171+
if err != nil {
172+
return err
173+
}
174+
v := entitlements.Values{
175+
NetworkHost: p.Meta.NetMode == pb.NetMode_HOST,
176+
SecurityInsecure: p.Meta.SecurityMode == pb.SecurityMode_INSECURE,
177+
}
178+
return ent.Check(v)
179+
}
180+
168181
func (b *llbBridge) Run(ctx context.Context, id string, rootfs executor.Mount, mounts []executor.Mount, process executor.ProcessInfo, started chan<- struct{}) (resourcestypes.Recorder, error) {
182+
if err := b.validateEntitlements(process); err != nil {
183+
return nil, err
184+
}
185+
169186
if err := b.loadExecutor(); err != nil {
170187
return nil, err
171188
}
172189
return b.executor.Run(ctx, id, rootfs, mounts, process, started)
173190
}
174191

175192
func (b *llbBridge) Exec(ctx context.Context, id string, process executor.ProcessInfo) error {
193+
if err := b.validateEntitlements(process); err != nil {
194+
return err
195+
}
196+
176197
if err := b.loadExecutor(); err != nil {
177198
return err
178199
}

solver/llbsolver/vertex.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,12 @@ func ValidateEntitlements(ent entitlements.Set) LoadOpt {
101101
return func(op *pb.Op, _ *pb.OpMetadata, opt *solver.VertexOptions) error {
102102
switch op := op.Op.(type) {
103103
case *pb.Op_Exec:
104-
if op.Exec.Network == pb.NetMode_HOST {
105-
if !ent.Allowed(entitlements.EntitlementNetworkHost) {
106-
return errors.Errorf("%s is not allowed", entitlements.EntitlementNetworkHost)
107-
}
104+
v := entitlements.Values{
105+
NetworkHost: op.Exec.Network == pb.NetMode_HOST,
106+
SecurityInsecure: op.Exec.Security == pb.SecurityMode_INSECURE,
108107
}
109-
110-
if op.Exec.Security == pb.SecurityMode_INSECURE {
111-
if !ent.Allowed(entitlements.EntitlementSecurityInsecure) {
112-
return errors.Errorf("%s is not allowed", entitlements.EntitlementSecurityInsecure)
113-
}
108+
if err := ent.Check(v); err != nil {
109+
return err
114110
}
115111
}
116112
return nil

util/entitlements/entitlements.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,23 @@ func (s Set) Allowed(e Entitlement) bool {
5858
_, ok := s[e]
5959
return ok
6060
}
61+
62+
func (s Set) Check(v Values) error {
63+
if v.NetworkHost {
64+
if !s.Allowed(EntitlementNetworkHost) {
65+
return errors.Errorf("%s is not allowed", EntitlementNetworkHost)
66+
}
67+
}
68+
69+
if v.SecurityInsecure {
70+
if !s.Allowed(EntitlementSecurityInsecure) {
71+
return errors.Errorf("%s is not allowed", EntitlementSecurityInsecure)
72+
}
73+
}
74+
return nil
75+
}
76+
77+
type Values struct {
78+
NetworkHost bool
79+
SecurityInsecure bool
80+
}

0 commit comments

Comments
 (0)