Merge pull request #41965 from thaJeztah/buildkit_apparmor_master
[master] Ensure AppArmor and SELinux profiles are applied when building with BuildKit
This commit is contained in:
commit
2bd6213363
|
@ -75,6 +75,7 @@ type Opt struct {
|
||||||
Rootless bool
|
Rootless bool
|
||||||
IdentityMapping *idtools.IdentityMapping
|
IdentityMapping *idtools.IdentityMapping
|
||||||
DNSConfig config.DNSConfig
|
DNSConfig config.DNSConfig
|
||||||
|
ApparmorProfile string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builder can build using BuildKit backend
|
// Builder can build using BuildKit backend
|
||||||
|
|
|
@ -132,7 +132,7 @@ func newController(rt http.RoundTripper, opt Opt) (*control.Controller, error) {
|
||||||
|
|
||||||
dns := getDNSConfig(opt.DNSConfig)
|
dns := getDNSConfig(opt.DNSConfig)
|
||||||
|
|
||||||
exec, err := newExecutor(root, opt.DefaultCgroupParent, opt.NetworkController, dns, opt.Rootless, opt.IdentityMapping)
|
exec, err := newExecutor(root, opt.DefaultCgroupParent, opt.NetworkController, dns, opt.Rootless, opt.IdentityMapping, opt.ApparmorProfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
|
|
||||||
const networkName = "bridge"
|
const networkName = "bridge"
|
||||||
|
|
||||||
func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, dnsConfig *oci.DNSConfig, rootless bool, idmap *idtools.IdentityMapping) (executor.Executor, error) {
|
func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, dnsConfig *oci.DNSConfig, rootless bool, idmap *idtools.IdentityMapping, apparmorProfile string) (executor.Executor, error) {
|
||||||
netRoot := filepath.Join(root, "net")
|
netRoot := filepath.Join(root, "net")
|
||||||
networkProviders := map[pb.NetMode]network.Provider{
|
networkProviders := map[pb.NetMode]network.Provider{
|
||||||
pb.NetMode_UNSET: &bridgeProvider{NetworkController: net, Root: netRoot},
|
pb.NetMode_UNSET: &bridgeProvider{NetworkController: net, Root: netRoot},
|
||||||
|
@ -52,6 +52,7 @@ func newExecutor(root, cgroupParent string, net libnetwork.NetworkController, dn
|
||||||
NoPivot: os.Getenv("DOCKER_RAMDISK") != "",
|
NoPivot: os.Getenv("DOCKER_RAMDISK") != "",
|
||||||
IdentityMapping: idmap,
|
IdentityMapping: idmap,
|
||||||
DNS: dnsConfig,
|
DNS: dnsConfig,
|
||||||
|
ApparmorProfile: apparmorProfile,
|
||||||
}, networkProviders)
|
}, networkProviders)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/moby/buildkit/executor/oci"
|
"github.com/moby/buildkit/executor/oci"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newExecutor(_, _ string, _ libnetwork.NetworkController, _ *oci.DNSConfig, _ bool, _ *idtools.IdentityMapping) (executor.Executor, error) {
|
func newExecutor(_, _ string, _ libnetwork.NetworkController, _ *oci.DNSConfig, _ bool, _ *idtools.IdentityMapping, _ string) (executor.Executor, error) {
|
||||||
return &winExecutor{}, nil
|
return &winExecutor{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -297,6 +297,7 @@ func newRouterOptions(config *config.Config, d *daemon.Daemon) (routerOptions, e
|
||||||
Rootless: d.Rootless(),
|
Rootless: d.Rootless(),
|
||||||
IdentityMapping: d.IdentityMapping(),
|
IdentityMapping: d.IdentityMapping(),
|
||||||
DNSConfig: config.DNSConfig,
|
DNSConfig: config.DNSConfig,
|
||||||
|
ApparmorProfile: daemon.DefaultApparmorProfile(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return opts, err
|
return opts, err
|
||||||
|
|
|
@ -15,6 +15,14 @@ const (
|
||||||
defaultAppArmorProfile = "docker-default"
|
defaultAppArmorProfile = "docker-default"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DefaultApparmorProfile returns the name of the default apparmor profile
|
||||||
|
func DefaultApparmorProfile() string {
|
||||||
|
if apparmor.IsEnabled() {
|
||||||
|
return defaultAppArmorProfile
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func ensureDefaultAppArmorProfile() error {
|
func ensureDefaultAppArmorProfile() error {
|
||||||
if apparmor.IsEnabled() {
|
if apparmor.IsEnabled() {
|
||||||
loaded, err := aaprofile.IsLoaded(defaultAppArmorProfile)
|
loaded, err := aaprofile.IsLoaded(defaultAppArmorProfile)
|
||||||
|
|
|
@ -5,3 +5,8 @@ package daemon // import "github.com/docker/docker/daemon"
|
||||||
func ensureDefaultAppArmorProfile() error {
|
func ensureDefaultAppArmorProfile() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultApparmorProfile returns an empty string.
|
||||||
|
func DefaultApparmorProfile() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ github.com/imdario/mergo 1afb36080aec31e0d1528973ebe6
|
||||||
golang.org/x/sync cd5d95a43a6e21273425c7ae415d3df9ea832eeb
|
golang.org/x/sync cd5d95a43a6e21273425c7ae415d3df9ea832eeb
|
||||||
|
|
||||||
# buildkit
|
# buildkit
|
||||||
github.com/moby/buildkit 8142d66b5ebde79846b869fba30d9d30633e74aa # v0.8.1
|
github.com/moby/buildkit 68bb095353c65bc3993fd534c26cf77fe05e61b1 # v0.8 branch
|
||||||
github.com/tonistiigi/fsutil 0834f99b7b85462efb69b4f571a4fa3ca7da5ac9
|
github.com/tonistiigi/fsutil 0834f99b7b85462efb69b4f571a4fa3ca7da5ac9
|
||||||
github.com/tonistiigi/units 6950e57a87eaf136bbe44ef2ec8e75b9e3569de2
|
github.com/tonistiigi/units 6950e57a87eaf136bbe44ef2ec8e75b9e3569de2
|
||||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||||
|
|
|
@ -87,6 +87,10 @@ type OCIConfig struct {
|
||||||
// Decoding this is delayed in order to remove the dependency from this
|
// Decoding this is delayed in order to remove the dependency from this
|
||||||
// config pkg to stargz snapshotter's config pkg.
|
// config pkg to stargz snapshotter's config pkg.
|
||||||
StargzSnapshotterConfig toml.Primitive `toml:"stargzSnapshotter"`
|
StargzSnapshotterConfig toml.Primitive `toml:"stargzSnapshotter"`
|
||||||
|
|
||||||
|
// ApparmorProfile is the name of the apparmor profile that should be used to constrain build containers.
|
||||||
|
// The profile should already be loaded (by a higher level system) before creating a worker.
|
||||||
|
ApparmorProfile string `toml:"apparmor-profile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContainerdConfig struct {
|
type ContainerdConfig struct {
|
||||||
|
@ -98,6 +102,10 @@ type ContainerdConfig struct {
|
||||||
GCConfig
|
GCConfig
|
||||||
NetworkConfig
|
NetworkConfig
|
||||||
Snapshotter string `toml:"snapshotter"`
|
Snapshotter string `toml:"snapshotter"`
|
||||||
|
|
||||||
|
// ApparmorProfile is the name of the apparmor profile that should be used to constrain build containers.
|
||||||
|
// The profile should already be loaded (by a higher level system) before creating a worker.
|
||||||
|
ApparmorProfile string `toml:"apparmor-profile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GCPolicy struct {
|
type GCPolicy struct {
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/moby/buildkit/snapshot"
|
"github.com/moby/buildkit/snapshot"
|
||||||
"github.com/moby/buildkit/util/network"
|
"github.com/moby/buildkit/util/network"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ const (
|
||||||
|
|
||||||
// GenerateSpec generates spec using containerd functionality.
|
// GenerateSpec generates spec using containerd functionality.
|
||||||
// opts are ignored for s.Process, s.Hostname, and s.Mounts .
|
// opts are ignored for s.Process, s.Hostname, and s.Mounts .
|
||||||
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, processMode ProcessMode, idmap *idtools.IdentityMapping, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
|
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, namespace network.Namespace, processMode ProcessMode, idmap *idtools.IdentityMapping, apparmorProfile string, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
|
||||||
c := &containers.Container{
|
c := &containers.Container{
|
||||||
ID: id,
|
ID: id,
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,7 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if securityOpts, err := generateSecurityOpts(meta.SecurityMode); err == nil {
|
if securityOpts, err := generateSecurityOpts(meta.SecurityMode, apparmorProfile); err == nil {
|
||||||
opts = append(opts, securityOpts...)
|
opts = append(opts, securityOpts...)
|
||||||
} else {
|
} else {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -103,6 +104,9 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
|
||||||
for _, f := range releasers {
|
for _, f := range releasers {
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
|
if s.Process.SelinuxLabel != "" {
|
||||||
|
selinux.ReleaseLabel(s.Process.SelinuxLabel)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range mounts {
|
for _, m := range mounts {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/moby/buildkit/util/entitlements/security"
|
"github.com/moby/buildkit/util/entitlements/security"
|
||||||
"github.com/moby/buildkit/util/system"
|
"github.com/moby/buildkit/util/system"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
|
func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
|
||||||
|
@ -26,15 +27,32 @@ func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
|
// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
|
||||||
func generateSecurityOpts(mode pb.SecurityMode) ([]oci.SpecOpts, error) {
|
func generateSecurityOpts(mode pb.SecurityMode, apparmorProfile string) (opts []oci.SpecOpts, _ error) {
|
||||||
if mode == pb.SecurityMode_INSECURE {
|
switch mode {
|
||||||
|
case pb.SecurityMode_INSECURE:
|
||||||
return []oci.SpecOpts{
|
return []oci.SpecOpts{
|
||||||
security.WithInsecureSpec(),
|
security.WithInsecureSpec(),
|
||||||
oci.WithWriteableCgroupfs,
|
oci.WithWriteableCgroupfs,
|
||||||
oci.WithWriteableSysfs,
|
oci.WithWriteableSysfs,
|
||||||
|
func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
|
||||||
|
var err error
|
||||||
|
s.Process.SelinuxLabel, s.Linux.MountLabel, err = label.InitLabels([]string{"disable"})
|
||||||
|
return err
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
} else if system.SeccompSupported() && mode == pb.SecurityMode_SANDBOX {
|
case pb.SecurityMode_SANDBOX:
|
||||||
return []oci.SpecOpts{withDefaultProfile()}, nil
|
if system.SeccompSupported() {
|
||||||
|
opts = append(opts, withDefaultProfile())
|
||||||
|
}
|
||||||
|
if apparmorProfile != "" {
|
||||||
|
opts = append(opts, oci.WithApparmorProfile(apparmorProfile))
|
||||||
|
}
|
||||||
|
opts = append(opts, func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
|
||||||
|
var err error
|
||||||
|
s.Process.SelinuxLabel, s.Linux.MountLabel, err = label.InitLabels(nil)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
return opts, nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ func generateMountOpts(resolvConf, hostsFile string) ([]oci.SpecOpts, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
|
// generateSecurityOpts may affect mounts, so must be called after generateMountOpts
|
||||||
func generateSecurityOpts(mode pb.SecurityMode) ([]oci.SpecOpts, error) {
|
func generateSecurityOpts(mode pb.SecurityMode, apparmorProfile string) ([]oci.SpecOpts, error) {
|
||||||
if mode == pb.SecurityMode_INSECURE {
|
if mode == pb.SecurityMode_INSECURE {
|
||||||
return nil, errors.New("no support for running in insecure mode on Windows")
|
return nil, errors.New("no support for running in insecure mode on Windows")
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,10 @@ type Opt struct {
|
||||||
ProcessMode oci.ProcessMode
|
ProcessMode oci.ProcessMode
|
||||||
IdentityMapping *idtools.IdentityMapping
|
IdentityMapping *idtools.IdentityMapping
|
||||||
// runc run --no-pivot (unrecommended)
|
// runc run --no-pivot (unrecommended)
|
||||||
NoPivot bool
|
NoPivot bool
|
||||||
DNS *oci.DNSConfig
|
DNS *oci.DNSConfig
|
||||||
OOMScoreAdj *int
|
OOMScoreAdj *int
|
||||||
|
ApparmorProfile string
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultCommandCandidates = []string{"buildkit-runc", "runc"}
|
var defaultCommandCandidates = []string{"buildkit-runc", "runc"}
|
||||||
|
@ -62,6 +63,7 @@ type runcExecutor struct {
|
||||||
oomScoreAdj *int
|
oomScoreAdj *int
|
||||||
running map[string]chan error
|
running map[string]chan error
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
apparmorProfile string
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Executor, error) {
|
func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Executor, error) {
|
||||||
|
@ -124,6 +126,7 @@ func New(opt Opt, networkProviders map[pb.NetMode]network.Provider) (executor.Ex
|
||||||
dns: opt.DNS,
|
dns: opt.DNS,
|
||||||
oomScoreAdj: opt.OOMScoreAdj,
|
oomScoreAdj: opt.OOMScoreAdj,
|
||||||
running: make(map[string]chan error),
|
running: make(map[string]chan error),
|
||||||
|
apparmorProfile: opt.ApparmorProfile,
|
||||||
}
|
}
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
@ -253,7 +256,7 @@ func (w *runcExecutor) Run(ctx context.Context, id string, root executor.Mount,
|
||||||
}
|
}
|
||||||
opts = append(opts, containerdoci.WithCgroup(cgroupsPath))
|
opts = append(opts, containerdoci.WithCgroup(cgroupsPath))
|
||||||
}
|
}
|
||||||
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.processMode, w.idmap, opts...)
|
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, namespace, w.processMode, w.idmap, w.apparmorProfile, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ require (
|
||||||
github.com/opencontainers/image-spec v1.0.1
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
github.com/opencontainers/runc v1.0.0-rc92
|
github.com/opencontainers/runc v1.0.0-rc92
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6
|
||||||
|
github.com/opencontainers/selinux v1.8.0
|
||||||
github.com/opentracing-contrib/go-stdlib v1.0.0
|
github.com/opentracing-contrib/go-stdlib v1.0.0
|
||||||
github.com/opentracing/opentracing-go v1.2.0
|
github.com/opentracing/opentracing-go v1.2.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
|
Loading…
Reference in New Issue