Skip to content

Commit

Permalink
Merge pull request #2994 from tonistiigi/device-entitlements
Browse files Browse the repository at this point in the history
support for device entitlement in build and bake
  • Loading branch information
crazy-max authored Feb 18, 2025
2 parents b04d394 + d0d3433 commit cdfc1ed
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 56 deletions.
5 changes: 1 addition & 4 deletions bake/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/session/auth/authprovider"
"github.com/moby/buildkit/util/entitlements"
"github.com/pkg/errors"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
Expand Down Expand Up @@ -1434,9 +1433,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
}
bo.Ulimits = ulimits

for _, ent := range t.Entitlements {
bo.Allow = append(bo.Allow, entitlements.Entitlement(ent))
}
bo.Allow = append(bo.Allow, t.Entitlements...)

return bo, nil
}
Expand Down
8 changes: 4 additions & 4 deletions bake/bake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1806,8 +1806,8 @@ func TestHCLEntitlements(t *testing.T) {
require.Equal(t, "network.host", m["app"].Entitlements[1])

require.Len(t, bo["app"].Allow, 2)
require.Equal(t, entitlements.EntitlementSecurityInsecure, bo["app"].Allow[0])
require.Equal(t, entitlements.EntitlementNetworkHost, bo["app"].Allow[1])
require.Equal(t, entitlements.EntitlementSecurityInsecure.String(), bo["app"].Allow[0])
require.Equal(t, entitlements.EntitlementNetworkHost.String(), bo["app"].Allow[1])
}

func TestEntitlementsForNetHostCompose(t *testing.T) {
Expand Down Expand Up @@ -1846,7 +1846,7 @@ func TestEntitlementsForNetHostCompose(t *testing.T) {
require.Equal(t, "host", *m["app"].NetworkMode)

require.Len(t, bo["app"].Allow, 1)
require.Equal(t, entitlements.EntitlementNetworkHost, bo["app"].Allow[0])
require.Equal(t, entitlements.EntitlementNetworkHost.String(), bo["app"].Allow[0])
require.Equal(t, "host", bo["app"].NetworkMode)
}

Expand Down Expand Up @@ -1877,7 +1877,7 @@ func TestEntitlementsForNetHost(t *testing.T) {
require.Equal(t, "host", *m["app"].NetworkMode)

require.Len(t, bo["app"].Allow, 1)
require.Equal(t, entitlements.EntitlementNetworkHost, bo["app"].Allow[0])
require.Equal(t, entitlements.EntitlementNetworkHost.String(), bo["app"].Allow[0])
require.Equal(t, "host", bo["app"].NetworkMode)
}

Expand Down
62 changes: 60 additions & 2 deletions bake/entitlements.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ import (
"github.com/moby/buildkit/util/entitlements"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/tonistiigi/go-csvvalue"
)

type EntitlementKey string

const (
EntitlementKeyNetworkHost EntitlementKey = "network.host"
EntitlementKeySecurityInsecure EntitlementKey = "security.insecure"
EntitlementKeyDevice EntitlementKey = "device"
EntitlementKeyFSRead EntitlementKey = "fs.read"
EntitlementKeyFSWrite EntitlementKey = "fs.write"
EntitlementKeyFS EntitlementKey = "fs"
Expand All @@ -39,13 +41,19 @@ const (
type EntitlementConf struct {
NetworkHost bool
SecurityInsecure bool
Devices *EntitlementsDevicesConf
FSRead []string
FSWrite []string
ImagePush []string
ImageLoad []string
SSH bool
}

type EntitlementsDevicesConf struct {
All bool
Devices map[string]struct{}
}

func ParseEntitlements(in []string) (EntitlementConf, error) {
var conf EntitlementConf
for _, e := range in {
Expand All @@ -59,6 +67,22 @@ func ParseEntitlements(in []string) (EntitlementConf, error) {
default:
k, v, _ := strings.Cut(e, "=")
switch k {
case string(EntitlementKeyDevice):
if v == "" {
conf.Devices = &EntitlementsDevicesConf{All: true}
continue
}
fields, err := csvvalue.Fields(v, nil)
if err != nil {
return EntitlementConf{}, errors.Wrapf(err, "failed to parse device entitlement %q", v)
}
if conf.Devices == nil {
conf.Devices = &EntitlementsDevicesConf{}
}
if conf.Devices.Devices == nil {
conf.Devices.Devices = make(map[string]struct{}, 0)
}
conf.Devices.Devices[fields[0]] = struct{}{}
case string(EntitlementKeyFSRead):
conf.FSRead = append(conf.FSRead, v)
case string(EntitlementKeyFSWrite):
Expand Down Expand Up @@ -95,12 +119,34 @@ func (c EntitlementConf) Validate(m map[string]build.Options) (EntitlementConf,

func (c EntitlementConf) check(bo build.Options, expected *EntitlementConf) error {
for _, e := range bo.Allow {
k, rest, _ := strings.Cut(e, "=")
switch k {
case entitlements.EntitlementDevice.String():
if rest == "" {
if c.Devices == nil || !c.Devices.All {
expected.Devices = &EntitlementsDevicesConf{All: true}
}
continue
}
fields, err := csvvalue.Fields(rest, nil)
if err != nil {
return errors.Wrapf(err, "failed to parse device entitlement %q", rest)
}
if expected.Devices == nil {
expected.Devices = &EntitlementsDevicesConf{}
}
if expected.Devices.Devices == nil {
expected.Devices.Devices = make(map[string]struct{}, 0)
}
expected.Devices.Devices[fields[0]] = struct{}{}
}

switch e {
case entitlements.EntitlementNetworkHost:
case entitlements.EntitlementNetworkHost.String():
if !c.NetworkHost {
expected.NetworkHost = true
}
case entitlements.EntitlementSecurityInsecure:
case entitlements.EntitlementSecurityInsecure.String():
if !c.SecurityInsecure {
expected.SecurityInsecure = true
}
Expand Down Expand Up @@ -187,6 +233,18 @@ func (c EntitlementConf) Prompt(ctx context.Context, isRemote bool, out io.Write
flags = append(flags, string(EntitlementKeySecurityInsecure))
}

if c.Devices != nil {
if c.Devices.All {
msgs = append(msgs, " - Access to CDI devices")
flags = append(flags, string(EntitlementKeyDevice))
} else {
for d := range c.Devices.Devices {
msgs = append(msgs, fmt.Sprintf(" - Access to device %s", d))
flags = append(flags, string(EntitlementKeyDevice)+"="+d)
}
}
}

if c.SSH {
msgsFS = append(msgsFS, " - Forwarding default SSH agent socket")
flagsFS = append(flagsFS, string(EntitlementKeySSH))
Expand Down
20 changes: 10 additions & 10 deletions bake/entitlements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ func TestValidateEntitlements(t *testing.T) {
{
name: "NetworkHostMissing",
opt: build.Options{
Allow: []entitlements.Entitlement{
entitlements.EntitlementNetworkHost,
Allow: []string{
entitlements.EntitlementNetworkHost.String(),
},
},
expected: EntitlementConf{
Expand All @@ -223,8 +223,8 @@ func TestValidateEntitlements(t *testing.T) {
NetworkHost: true,
},
opt: build.Options{
Allow: []entitlements.Entitlement{
entitlements.EntitlementNetworkHost,
Allow: []string{
entitlements.EntitlementNetworkHost.String(),
},
},
expected: EntitlementConf{
Expand All @@ -234,9 +234,9 @@ func TestValidateEntitlements(t *testing.T) {
{
name: "SecurityAndNetworkHostMissing",
opt: build.Options{
Allow: []entitlements.Entitlement{
entitlements.EntitlementNetworkHost,
entitlements.EntitlementSecurityInsecure,
Allow: []string{
entitlements.EntitlementNetworkHost.String(),
entitlements.EntitlementSecurityInsecure.String(),
},
},
expected: EntitlementConf{
Expand All @@ -251,9 +251,9 @@ func TestValidateEntitlements(t *testing.T) {
NetworkHost: true,
},
opt: build.Options{
Allow: []entitlements.Entitlement{
entitlements.EntitlementNetworkHost,
entitlements.EntitlementSecurityInsecure,
Allow: []string{
entitlements.EntitlementNetworkHost.String(),
entitlements.EntitlementSecurityInsecure.String(),
},
},
expected: EntitlementConf{
Expand Down
3 changes: 1 addition & 2 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import (
"github.com/moby/buildkit/solver/errdefs"
"github.com/moby/buildkit/solver/pb"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/entitlements"
"github.com/moby/buildkit/util/progress/progresswriter"
"github.com/moby/buildkit/util/tracing"
"github.com/opencontainers/go-digest"
Expand All @@ -63,7 +62,7 @@ type Options struct {
Inputs Inputs

Ref string
Allow []entitlements.Entitlement
Allow []string
Attests map[string]*string
BuildArgs map[string]string
CacheFrom []client.CacheOptionsEntry
Expand Down
2 changes: 1 addition & 1 deletion build/opt.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *O
switch opt.NetworkMode {
case "host":
so.FrontendAttrs["force-network-mode"] = opt.NetworkMode
so.AllowedEntitlements = append(so.AllowedEntitlements, entitlements.EntitlementNetworkHost)
so.AllowedEntitlements = append(so.AllowedEntitlements, entitlements.EntitlementNetworkHost.String())
case "none":
so.FrontendAttrs["force-network-mode"] = opt.NetworkMode
case "", "default":
Expand Down
2 changes: 1 addition & 1 deletion commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions, debugConfig *debug.D

flags.StringSliceVar(&options.extraHosts, "add-host", []string{}, `Add a custom host-to-IP mapping (format: "host:ip")`)

flags.StringSliceVar(&options.allow, "allow", []string{}, `Allow extra privileged entitlement (e.g., "network.host", "security.insecure")`)
flags.StringArrayVar(&options.allow, "allow", []string{}, `Allow extra privileged entitlement (e.g., "network.host", "security.insecure")`)

flags.StringArrayVarP(&options.annotations, "annotation", "", []string{}, "Add annotation to the image")

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/buildx_build.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Start a build
| Name | Type | Default | Description |
|:----------------------------------------|:--------------|:----------|:-------------------------------------------------------------------------------------------------------------|
| [`--add-host`](#add-host) | `stringSlice` | | Add a custom host-to-IP mapping (format: `host:ip`) |
| [`--allow`](#allow) | `stringSlice` | | Allow extra privileged entitlement (e.g., `network.host`, `security.insecure`) |
| [`--allow`](#allow) | `stringArray` | | Allow extra privileged entitlement (e.g., `network.host`, `security.insecure`) |
| [`--annotation`](#annotation) | `stringArray` | | Add annotation to the image |
| [`--attest`](#attest) | `stringArray` | | Attestation parameters (format: `type=sbom,generator=image`) |
| [`--build-arg`](#build-arg) | `stringArray` | | Set build-time variables |
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/buildx_debug_build.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Start a build
| Name | Type | Default | Description |
|:--------------------|:--------------|:----------|:-------------------------------------------------------------------------------------------------------------|
| `--add-host` | `stringSlice` | | Add a custom host-to-IP mapping (format: `host:ip`) |
| `--allow` | `stringSlice` | | Allow extra privileged entitlement (e.g., `network.host`, `security.insecure`) |
| `--allow` | `stringArray` | | Allow extra privileged entitlement (e.g., `network.host`, `security.insecure`) |
| `--annotation` | `stringArray` | | Add annotation to the image |
| `--attest` | `stringArray` | | Attestation parameters (format: `type=sbom,generator=image`) |
| `--build-arg` | `stringArray` | | Set build-time variables |
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ require (
github.com/hashicorp/hcl/v2 v2.23.0
github.com/in-toto/in-toto-golang v0.5.0
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/moby/buildkit v0.20.0-rc2
github.com/moby/buildkit v0.20.0-rc3
github.com/moby/sys/mountinfo v0.7.2
github.com/moby/sys/signal v0.7.1
github.com/morikuni/aec v1.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/z
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/buildkit v0.20.0-rc2 h1:QjACghvG0pSAp7dk9aQMYWioDEOljDWyyoUjyg35qfg=
github.com/moby/buildkit v0.20.0-rc2/go.mod h1:kMXf90l/f3zygRK8bYbyetfyzoJYntb6Bpi2VsLfXgQ=
github.com/moby/buildkit v0.20.0-rc3 h1:iExrfuZZuFgFudeNJhXfp/5vzJWTNrlqZ/LYJk4dG2Q=
github.com/moby/buildkit v0.20.0-rc3/go.mod h1:kMXf90l/f3zygRK8bYbyetfyzoJYntb6Bpi2VsLfXgQ=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
Expand Down
17 changes: 11 additions & 6 deletions util/buildflags/entitlements.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package buildflags

import "github.com/moby/buildkit/util/entitlements"
import (
"log"

func ParseEntitlements(in []string) ([]entitlements.Entitlement, error) {
out := make([]entitlements.Entitlement, 0, len(in))
"github.com/moby/buildkit/util/entitlements"
)

func ParseEntitlements(in []string) ([]string, error) {
out := make([]string, 0, len(in))
log.Printf("in: %#v", in)
for _, v := range in {
if v == "" {
continue
}

e, err := entitlements.Parse(v)
if err != nil {
if _, _, err := entitlements.Parse(v); err != nil {
return nil, err
}
out = append(out, e)
out = append(out, v)
}
log.Printf("Parsed entitlements: %v", out)
return out, nil
}
14 changes: 3 additions & 11 deletions vendor/github.com/moby/buildkit/client/solve.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cdfc1ed

Please sign in to comment.