diff --git a/go.mod b/go.mod index 3abcfd2f96..27a362d645 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/buger/goterm v1.0.4 - github.com/compose-spec/compose-go/v2 v2.0.2 + github.com/compose-spec/compose-go/v2 v2.0.3-0.20240407191136-f388192b8a39 github.com/containerd/console v1.0.4 github.com/containerd/containerd v1.7.13 github.com/davecgh/go-spew v1.1.1 diff --git a/go.sum b/go.sum index 36720a4156..7a97c621f7 100644 --- a/go.sum +++ b/go.sum @@ -90,8 +90,8 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= -github.com/compose-spec/compose-go/v2 v2.0.2 h1:zhXMV7VWI00Su0LdKt8/sxeXxcjLWhmGmpEyw+ZYznI= -github.com/compose-spec/compose-go/v2 v2.0.2/go.mod h1:bEPizBkIojlQ20pi2vNluBa58tevvj0Y18oUSHPyfdc= +github.com/compose-spec/compose-go/v2 v2.0.3-0.20240407191136-f388192b8a39 h1:ZUpnv0xA75X9gy9Y7hjJm51nflGbr+2URaLXBtEic7A= +github.com/compose-spec/compose-go/v2 v2.0.3-0.20240407191136-f388192b8a39/go.mod h1:bEPizBkIojlQ20pi2vNluBa58tevvj0Y18oUSHPyfdc= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= diff --git a/pkg/compose/build.go b/pkg/compose/build.go index 8dacba1ba4..89cc48bba0 100644 --- a/pkg/compose/build.go +++ b/pkg/compose/build.go @@ -388,7 +388,11 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se if len(service.Build.Tags) > 0 { tags = append(tags, service.Build.Tags...) } - var allow []entitlements.Entitlement + + allow, err := buildflags.ParseEntitlements(service.Build.Entitlements) + if err != nil { + return build.Options{}, err + } if service.Build.Privileged { allow = append(allow, entitlements.EntitlementSecurityInsecure) } diff --git a/pkg/e2e/build_test.go b/pkg/e2e/build_test.go index 65044519b5..8c87b99c29 100644 --- a/pkg/e2e/build_test.go +++ b/pkg/e2e/build_test.go @@ -471,3 +471,35 @@ func TestBuildBuilder(t *testing.T) { }) } + +func TestBuildEntitlements(t *testing.T) { + c := NewParallelCLI(t) + + // declare builder + result := c.RunDockerCmd(t, "buildx", "create", "--name", "build-insecure", "--use", "--bootstrap", "--buildkitd-flags", + `'--allow-insecure-entitlement=security.insecure'`) + assert.NilError(t, result.Error) + + t.Cleanup(func() { + c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test/entitlements", "down") + _ = c.RunDockerCmd(t, "buildx", "rm", "-f", "build-insecure") + }) + + t.Run("use build privileged mode to run insecure build command", func(t *testing.T) { + res := c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test/entitlements", "build") + capEffRe := regexp.MustCompile("CapEff:\t([0-9a-f]+)") + matches := capEffRe.FindStringSubmatch(res.Stdout()) + assert.Equal(t, 2, len(matches), "Did not match CapEff in output, matches: %v", matches) + + capEff, err := strconv.ParseUint(matches[1], 16, 64) + assert.NilError(t, err, "Parsing CapEff: %s", matches[1]) + + // NOTE: can't use constant from x/sys/unix or tests won't compile on macOS/Windows + // #define CAP_SYS_ADMIN 21 + // https://github.com/torvalds/linux/blob/v6.1/include/uapi/linux/capability.h#L278 + const capSysAdmin = 0x15 + if capEff&capSysAdmin != capSysAdmin { + t.Fatalf("CapEff %s is missing CAP_SYS_ADMIN", matches[1]) + } + }) +} diff --git a/pkg/e2e/fixtures/build-test/entitlements/Dockerfile b/pkg/e2e/fixtures/build-test/entitlements/Dockerfile new file mode 100644 index 0000000000..a242eb52d4 --- /dev/null +++ b/pkg/e2e/fixtures/build-test/entitlements/Dockerfile @@ -0,0 +1,19 @@ +# syntax = docker/dockerfile:experimental + + +# Copyright 2020 Docker Compose CLI authors + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM alpine +RUN --security=insecure cat /proc/self/status | grep CapEff diff --git a/pkg/e2e/fixtures/build-test/entitlements/compose.yaml b/pkg/e2e/fixtures/build-test/entitlements/compose.yaml new file mode 100644 index 0000000000..403529e647 --- /dev/null +++ b/pkg/e2e/fixtures/build-test/entitlements/compose.yaml @@ -0,0 +1,7 @@ +services: + privileged-service: + build: + context: . + entitlements: + - security.insecure +