Add proper SELinux labeling to buildah run
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #294 Approved by: nalind
This commit is contained in:
parent
cde99f8517
commit
966f32b2ac
1
.papr.sh
1
.papr.sh
|
@ -21,6 +21,7 @@ dnf install -y \
|
||||||
libassuan-devel \
|
libassuan-devel \
|
||||||
libseccomp-devel \
|
libseccomp-devel \
|
||||||
libselinux-devel \
|
libselinux-devel \
|
||||||
|
libselinux-utils \
|
||||||
make \
|
make \
|
||||||
ostree-devel \
|
ostree-devel \
|
||||||
which
|
which
|
||||||
|
|
|
@ -77,6 +77,10 @@ type Builder struct {
|
||||||
// MountPoint is the last location where the container's root
|
// MountPoint is the last location where the container's root
|
||||||
// filesystem was mounted. It should not be modified.
|
// filesystem was mounted. It should not be modified.
|
||||||
MountPoint string `json:"mountpoint,omitempty"`
|
MountPoint string `json:"mountpoint,omitempty"`
|
||||||
|
// ProcessLabel is the SELinux process label associated with the container
|
||||||
|
ProcessLabel string `json:"process-label,omitempty"`
|
||||||
|
// MountLabel is the SELinux mount label associated with the container
|
||||||
|
MountLabel string `json:"mount-label,omitempty"`
|
||||||
|
|
||||||
// ImageAnnotations is a set of key-value pairs which is stored in the
|
// ImageAnnotations is a set of key-value pairs which is stored in the
|
||||||
// image's manifest.
|
// image's manifest.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package buildah
|
package buildah
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,5 +14,5 @@ func (b *Builder) Delete() error {
|
||||||
b.MountPoint = ""
|
b.MountPoint = ""
|
||||||
b.Container = ""
|
b.Container = ""
|
||||||
b.ContainerID = ""
|
b.ContainerID = ""
|
||||||
return nil
|
return label.ReleaseLabel(b.ProcessLabel)
|
||||||
}
|
}
|
||||||
|
|
44
new.go
44
new.go
|
@ -9,6 +9,8 @@ import (
|
||||||
"github.com/containers/image/transports/alltransports"
|
"github.com/containers/image/transports/alltransports"
|
||||||
"github.com/containers/image/types"
|
"github.com/containers/image/types"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
"github.com/openshift/imagebuilder"
|
"github.com/openshift/imagebuilder"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -25,8 +27,35 @@ const (
|
||||||
DefaultTransport = "docker://"
|
DefaultTransport = "docker://"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func reserveSELinuxLabels(store storage.Store, id string) error {
|
||||||
|
if selinux.GetEnabled() {
|
||||||
|
containers, err := store.Containers()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range containers {
|
||||||
|
if id == c.ID {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
b, err := OpenBuilder(store, c.ID)
|
||||||
|
if err != nil {
|
||||||
|
if err == storage.ErrContainerUnknown {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Prevent containers from using same MCS Label
|
||||||
|
if err := label.ReserveLabel(b.ProcessLabel); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
|
func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
|
||||||
var err error
|
|
||||||
var ref types.ImageReference
|
var ref types.ImageReference
|
||||||
var img *storage.Image
|
var img *storage.Image
|
||||||
manifest := []byte{}
|
manifest := []byte{}
|
||||||
|
@ -45,6 +74,7 @@ func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
|
||||||
|
|
||||||
imageID := ""
|
imageID := ""
|
||||||
if image != "" {
|
if image != "" {
|
||||||
|
var err error
|
||||||
if options.PullPolicy == PullAlways {
|
if options.PullPolicy == PullAlways {
|
||||||
pulledReference, err2 := pullImage(store, options, systemContext)
|
pulledReference, err2 := pullImage(store, options, systemContext)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
|
@ -158,6 +188,14 @@ func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if err := reserveSELinuxLabels(store, container.ID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
processLabel, mountLabel, err := label.InitLabels(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
builder := &Builder{
|
builder := &Builder{
|
||||||
store: store,
|
store: store,
|
||||||
Type: containerType,
|
Type: containerType,
|
||||||
|
@ -169,10 +207,12 @@ func newBuilder(store storage.Store, options BuilderOptions) (*Builder, error) {
|
||||||
ContainerID: container.ID,
|
ContainerID: container.ID,
|
||||||
ImageAnnotations: map[string]string{},
|
ImageAnnotations: map[string]string{},
|
||||||
ImageCreatedBy: "",
|
ImageCreatedBy: "",
|
||||||
|
ProcessLabel: processLabel,
|
||||||
|
MountLabel: mountLabel,
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.Mount {
|
if options.Mount {
|
||||||
_, err = builder.Mount("")
|
_, err = builder.Mount(mountLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error mounting build container")
|
return nil, errors.Wrapf(err, "error mounting build container")
|
||||||
}
|
}
|
||||||
|
|
4
run.go
4
run.go
|
@ -182,7 +182,9 @@ func (b *Builder) Run(command []string, options RunOptions) error {
|
||||||
} else if b.Hostname() != "" {
|
} else if b.Hostname() != "" {
|
||||||
g.SetHostname(b.Hostname())
|
g.SetHostname(b.Hostname())
|
||||||
}
|
}
|
||||||
mountPoint, err := b.Mount("")
|
g.SetProcessSelinuxLabel(b.ProcessLabel)
|
||||||
|
g.SetLinuxMountLabel(b.MountLabel)
|
||||||
|
mountPoint, err := b.Mount(b.MountLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
load helpers
|
||||||
|
|
||||||
|
@test "selinux test" {
|
||||||
|
if ! which selinuxenabled ; then
|
||||||
|
skip "No selinuxenabled"
|
||||||
|
elif ! /usr/sbin/selinuxenabled; then
|
||||||
|
skip "selinux is disabled"
|
||||||
|
fi
|
||||||
|
image=alpine
|
||||||
|
cid=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json $image)
|
||||||
|
firstlabel=$(buildah --debug=false run $cid cat /proc/1/attr/current)
|
||||||
|
run buildah --debug=false run $cid cat /proc/1/attr/current
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[ "$output" == $firstlabel ]
|
||||||
|
|
||||||
|
cid1=$(buildah from --pull --signature-policy ${TESTSDIR}/policy.json $image)
|
||||||
|
run buildah --debug=false run $cid1 cat /proc/1/attr/current
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[ "$output" != $firstlabel ]
|
||||||
|
|
||||||
|
buildah rm $cid
|
||||||
|
buildah rm $cid1
|
||||||
|
}
|
||||||
|
|
|
@ -17,5 +17,5 @@ exec gometalinter.v1 \
|
||||||
--disable=gas \
|
--disable=gas \
|
||||||
--disable=aligncheck \
|
--disable=aligncheck \
|
||||||
--cyclo-over=40 \
|
--cyclo-over=40 \
|
||||||
--deadline=240s \
|
--deadline=480s \
|
||||||
--tests "$@"
|
--tests "$@"
|
||||||
|
|
|
@ -27,7 +27,7 @@ github.com/opencontainers/image-spec v1.0.0
|
||||||
github.com/opencontainers/runc master
|
github.com/opencontainers/runc master
|
||||||
github.com/opencontainers/runtime-spec v1.0.0
|
github.com/opencontainers/runtime-spec v1.0.0
|
||||||
github.com/opencontainers/runtime-tools master
|
github.com/opencontainers/runtime-tools master
|
||||||
github.com/opencontainers/selinux ba1aefe8057f1d0cfb8e88d0ec1dc85925ef987d
|
github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd
|
||||||
github.com/openshift/imagebuilder master
|
github.com/openshift/imagebuilder master
|
||||||
github.com/ostreedev/ostree-go aeb02c6b6aa2889db3ef62f7855650755befd460
|
github.com/ostreedev/ostree-go aeb02c6b6aa2889db3ef62f7855650755befd460
|
||||||
github.com/pborman/uuid master
|
github.com/pborman/uuid master
|
||||||
|
|
|
@ -49,8 +49,10 @@ func InitLabels(options []string) (string, string, error) {
|
||||||
mcon[con[0]] = con[1]
|
mcon[con[0]] = con[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ = ReleaseLabel(processLabel)
|
||||||
processLabel = pcon.Get()
|
processLabel = pcon.Get()
|
||||||
mountLabel = mcon.Get()
|
mountLabel = mcon.Get()
|
||||||
|
_ = ReserveLabel(processLabel)
|
||||||
}
|
}
|
||||||
return processLabel, mountLabel, nil
|
return processLabel, mountLabel, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,7 @@ func SetFileLabel(path string, label string) error {
|
||||||
return lsetxattr(path, xattrNameSelinux, []byte(label), 0)
|
return lsetxattr(path, xattrNameSelinux, []byte(label), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filecon returns the SELinux label for this path or returns an error.
|
// FileLabel returns the SELinux label for this path or returns an error.
|
||||||
func FileLabel(path string) (string, error) {
|
func FileLabel(path string) (string, error) {
|
||||||
label, err := lgetxattr(path, xattrNameSelinux)
|
label, err := lgetxattr(path, xattrNameSelinux)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -331,7 +331,7 @@ func EnforceMode() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SetEnforce sets the current SELinux mode Enforcing, Permissive.
|
SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
|
||||||
Disabled is not valid, since this needs to be set at boot time.
|
Disabled is not valid, since this needs to be set at boot time.
|
||||||
*/
|
*/
|
||||||
func SetEnforceMode(mode int) error {
|
func SetEnforceMode(mode int) error {
|
||||||
|
|
Loading…
Reference in New Issue