Add SELinux support to OCID
Signed-off-by: Dan Walsh <dwalsh@redhat.com>
This commit is contained in:
parent
308cc4a3b5
commit
be77b841fa
5 changed files with 84 additions and 44 deletions
3
Makefile
3
Makefile
|
@ -11,6 +11,7 @@ PREFIX ?= ${DESTDIR}/usr
|
||||||
INSTALLDIR=${PREFIX}/bin
|
INSTALLDIR=${PREFIX}/bin
|
||||||
GO_MD2MAN ?= $(shell which go-md2man)
|
GO_MD2MAN ?= $(shell which go-md2man)
|
||||||
export GOPATH := ${CURDIR}/vendor
|
export GOPATH := ${CURDIR}/vendor
|
||||||
|
BUILDTAGS := selinux
|
||||||
|
|
||||||
default: help
|
default: help
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ pause:
|
||||||
make -C $@
|
make -C $@
|
||||||
|
|
||||||
ocid: ${OCID_LINK}
|
ocid: ${OCID_LINK}
|
||||||
go build -o ocid ./cmd/server/
|
go build --tags "$(BUILDTAGS)" -o ocid ./cmd/server/
|
||||||
|
|
||||||
ocic: ${OCID_LINK}
|
ocic: ${OCID_LINK}
|
||||||
go build -o ocic ./cmd/client/
|
go build -o ocic ./cmd/client/
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/kubernetes-incubator/cri-o/server"
|
"github.com/kubernetes-incubator/cri-o/server"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/selinux"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||||
|
@ -65,6 +66,10 @@ func main() {
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
Usage: "enable debug output for logging",
|
Usage: "enable debug output for logging",
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "selinux-enabled",
|
||||||
|
Usage: "enable selinux support",
|
||||||
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "log",
|
Name: "log",
|
||||||
Value: "",
|
Value: "",
|
||||||
|
@ -81,6 +86,9 @@ func main() {
|
||||||
if c.GlobalBool("debug") {
|
if c.GlobalBool("debug") {
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
logrus.SetLevel(logrus.DebugLevel)
|
||||||
}
|
}
|
||||||
|
if !c.GlobalBool("selinux-enabled") {
|
||||||
|
selinux.SetDisabled()
|
||||||
|
}
|
||||||
if path := c.GlobalString("log"); path != "" {
|
if path := c.GlobalString("log"); path != "" {
|
||||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0666)
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -5,11 +5,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/docker/pkg/stringid"
|
"github.com/docker/docker/pkg/stringid"
|
||||||
"github.com/kubernetes-incubator/cri-o/oci"
|
"github.com/kubernetes-incubator/cri-o/oci"
|
||||||
"github.com/kubernetes-incubator/cri-o/utils"
|
"github.com/kubernetes-incubator/cri-o/utils"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/label"
|
||||||
"github.com/opencontainers/runtime-tools/generate"
|
"github.com/opencontainers/runtime-tools/generate"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||||
|
@ -161,8 +163,12 @@ func (s *Server) createSandboxContainer(containerID string, containerName string
|
||||||
options = "ro"
|
options = "ro"
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO(hmeng): how to use this info? Do we need to handle relabel a FS with Selinux?
|
if mount.GetSelinuxRelabel() {
|
||||||
//selinuxRelabel := mount.GetSelinuxRelabel()
|
// Need a way in kubernetes to determine if the volume is shared or private
|
||||||
|
if err := label.Relabel(src, sb.mountLabel, true); err != nil && err != syscall.ENOTSUP {
|
||||||
|
return nil, fmt.Errorf("relabel failed %s: %v", src, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
specgen.AddBindMount(src, dest, options)
|
specgen.AddBindMount(src, dest, options)
|
||||||
|
|
||||||
|
@ -240,30 +246,8 @@ func (s *Server) createSandboxContainer(containerID string, containerName string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selinuxOptions := linux.GetSelinuxOptions()
|
specgen.SetProcessSelinuxLabel(sb.processLabel)
|
||||||
if selinuxOptions != nil {
|
specgen.SetLinuxMountLabel(sb.mountLabel)
|
||||||
user := selinuxOptions.GetUser()
|
|
||||||
if user == "" {
|
|
||||||
return nil, fmt.Errorf("SELinuxOption.User is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
role := selinuxOptions.GetRole()
|
|
||||||
if role == "" {
|
|
||||||
return nil, fmt.Errorf("SELinuxOption.Role is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
t := selinuxOptions.GetType()
|
|
||||||
if t == "" {
|
|
||||||
return nil, fmt.Errorf("SELinuxOption.Type is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
level := selinuxOptions.GetLevel()
|
|
||||||
if level == "" {
|
|
||||||
return nil, fmt.Errorf("SELinuxOption.Level is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
specgen.SetProcessSelinuxLabel(fmt.Sprintf("%s:%s:%s:%s", user, role, t, level))
|
|
||||||
}
|
|
||||||
|
|
||||||
user := linux.GetUser()
|
user := linux.GetUser()
|
||||||
if user != nil {
|
if user != nil {
|
||||||
|
|
|
@ -10,18 +10,21 @@ import (
|
||||||
"github.com/docker/docker/pkg/stringid"
|
"github.com/docker/docker/pkg/stringid"
|
||||||
"github.com/kubernetes-incubator/cri-o/oci"
|
"github.com/kubernetes-incubator/cri-o/oci"
|
||||||
"github.com/kubernetes-incubator/cri-o/utils"
|
"github.com/kubernetes-incubator/cri-o/utils"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/label"
|
||||||
"github.com/opencontainers/runtime-tools/generate"
|
"github.com/opencontainers/runtime-tools/generate"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sandbox struct {
|
type sandbox struct {
|
||||||
id string
|
id string
|
||||||
name string
|
name string
|
||||||
logDir string
|
logDir string
|
||||||
labels map[string]string
|
labels map[string]string
|
||||||
annotations map[string]string
|
annotations map[string]string
|
||||||
containers oci.Store
|
containers oci.Store
|
||||||
|
processLabel string
|
||||||
|
mountLabel string
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -58,6 +61,7 @@ func (s *Server) generatePodIDandName(name string, namespace string, attempt uin
|
||||||
|
|
||||||
// RunPodSandbox creates and runs a pod-level sandbox.
|
// RunPodSandbox creates and runs a pod-level sandbox.
|
||||||
func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest) (*pb.RunPodSandboxResponse, error) {
|
func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest) (*pb.RunPodSandboxResponse, error) {
|
||||||
|
var processLabel, mountLabel string
|
||||||
// process req.Name
|
// process req.Name
|
||||||
name := req.GetConfig().GetMetadata().GetName()
|
name := req.GetConfig().GetMetadata().GetName()
|
||||||
if name == "" {
|
if name == "" {
|
||||||
|
@ -140,6 +144,11 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processLabel, mountLabel, err = getSELinuxLabels(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
containerID, containerName, err := s.generateContainerIDandName(name, "infra", 0)
|
containerID, containerName, err := s.generateContainerIDandName(name, "infra", 0)
|
||||||
g.AddAnnotation("ocid/labels", string(labelsJSON))
|
g.AddAnnotation("ocid/labels", string(labelsJSON))
|
||||||
g.AddAnnotation("ocid/annotations", string(annotationsJSON))
|
g.AddAnnotation("ocid/annotations", string(annotationsJSON))
|
||||||
|
@ -148,12 +157,14 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest
|
||||||
g.AddAnnotation("ocid/container_name", containerName)
|
g.AddAnnotation("ocid/container_name", containerName)
|
||||||
g.AddAnnotation("ocid/container_id", containerID)
|
g.AddAnnotation("ocid/container_id", containerID)
|
||||||
s.addSandbox(&sandbox{
|
s.addSandbox(&sandbox{
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
logDir: logDir,
|
logDir: logDir,
|
||||||
labels: labels,
|
labels: labels,
|
||||||
annotations: annotations,
|
annotations: annotations,
|
||||||
containers: oci.NewMemoryStore(),
|
containers: oci.NewMemoryStore(),
|
||||||
|
processLabel: processLabel,
|
||||||
|
mountLabel: mountLabel,
|
||||||
})
|
})
|
||||||
|
|
||||||
for k, v := range annotations {
|
for k, v := range annotations {
|
||||||
|
@ -442,3 +453,30 @@ func (s *Server) ListPodSandbox(context.Context, *pb.ListPodSandboxRequest) (*pb
|
||||||
Items: pods,
|
Items: pods,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSELinuxLabels(selinuxOptions *pb.SELinuxOption) (processLabel string, mountLabel string, err error) {
|
||||||
|
processLabel = ""
|
||||||
|
if selinuxOptions != nil {
|
||||||
|
user := selinuxOptions.GetUser()
|
||||||
|
if user == "" {
|
||||||
|
return "", "", fmt.Errorf("SELinuxOption.User is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
role := selinuxOptions.GetRole()
|
||||||
|
if role == "" {
|
||||||
|
return "", "", fmt.Errorf("SELinuxOption.Role is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
t := selinuxOptions.GetType()
|
||||||
|
if t == "" {
|
||||||
|
return "", "", fmt.Errorf("SELinuxOption.Type is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
level := selinuxOptions.GetLevel()
|
||||||
|
if level == "" {
|
||||||
|
return "", "", fmt.Errorf("SELinuxOption.Level is empty")
|
||||||
|
}
|
||||||
|
processLabel = fmt.Sprintf("%s:%s:%s:%s", user, role, t, level)
|
||||||
|
}
|
||||||
|
return label.InitLabels(label.DupSecOpt(processLabel))
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/docker/docker/pkg/truncindex"
|
"github.com/docker/docker/pkg/truncindex"
|
||||||
"github.com/kubernetes-incubator/cri-o/oci"
|
"github.com/kubernetes-incubator/cri-o/oci"
|
||||||
"github.com/kubernetes-incubator/cri-o/utils"
|
"github.com/kubernetes-incubator/cri-o/utils"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/label"
|
||||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/rajatchopra/ocicni"
|
"github.com/rajatchopra/ocicni"
|
||||||
)
|
)
|
||||||
|
@ -55,14 +56,22 @@ func (s *Server) loadSandbox(id string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processLabel, mountLabel, err := label.InitLabels(label.DupSecOpt(m.Process.SelinuxLabel))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
s.addSandbox(&sandbox{
|
s.addSandbox(&sandbox{
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
logDir: m.Annotations["ocid/log_path"],
|
logDir: m.Annotations["ocid/log_path"],
|
||||||
labels: labels,
|
labels: labels,
|
||||||
containers: oci.NewMemoryStore(),
|
containers: oci.NewMemoryStore(),
|
||||||
|
processLabel: processLabel,
|
||||||
|
mountLabel: mountLabel,
|
||||||
})
|
})
|
||||||
sandboxPath := filepath.Join(s.sandboxDir, id)
|
sandboxPath := filepath.Join(s.sandboxDir, id)
|
||||||
|
|
||||||
scontainer, err := oci.NewContainer(m.Annotations["ocid/container_id"], m.Annotations["ocid/container_name"], sandboxPath, sandboxPath, labels, id, false)
|
scontainer, err := oci.NewContainer(m.Annotations["ocid/container_id"], m.Annotations["ocid/container_name"], sandboxPath, sandboxPath, labels, id, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
Loading…
Reference in a new issue