Skip to content
This repository has been archived by the owner on Mar 31, 2023. It is now read-only.

Commit

Permalink
Merge pull request #137 from weaveworks/fix_selinux_permissive
Browse files Browse the repository at this point in the history
Fix SELinux permissive mode detection logic
  • Loading branch information
chanwit committed Mar 31, 2020
2 parents de79207 + 70dc9a8 commit 064057d
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 87 deletions.
2 changes: 1 addition & 1 deletion pkg/apis/wksprovider/controller/wksctl/machine_actuator.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func (a *MachineActuator) update(ctx context.Context, cluster *clusterv1.Cluster

if diffedPlan, err := plandiff.GetUnifiedDiff(currentPlan, planJSON); err == nil {
contextLog.Info("........................ DIFF PLAN ........................")
contextLog.Info(diffedPlan)
fmt.Print(diffedPlan)
} else {
contextLog.Errorf("DIFF PLAN Error: %v", err)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/apis/wksprovider/machine/os/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ func (o OS) CreateSeedNodeSetupPlan(params SeedNodeParams) (*plan.Plan, error) {
criRes := recipe.BuildCRIPlan(&providerSpec.CRI, cfg, o.PkgType)
b.AddResource("install:cri", criRes, plan.DependOn("install:config"))

k8sRes := recipe.BuildK8SPlan(kubernetesVersion, params.KubeletConfig.NodeIP, cfg.SetSELinuxPermissive, cfg.DisableSwap, cfg.LockYUMPkgs, o.PkgType, params.KubeletConfig.CloudProvider)
k8sRes := recipe.BuildK8SPlan(kubernetesVersion, params.KubeletConfig.NodeIP, cfg.SELinuxInstalled, cfg.SetSELinuxPermissive, cfg.DisableSwap, cfg.LockYUMPkgs, o.PkgType, params.KubeletConfig.CloudProvider)
b.AddResource("install:k8s", k8sRes, plan.DependOn("install:cri"))

apiServerArgs := getAPIServerArgs(providerSpec, pemSecretResources)
Expand Down Expand Up @@ -1041,7 +1041,7 @@ func (o OS) CreateNodeSetupPlan(params NodeParams) (*plan.Plan, error) {
instCriRsrc := recipe.BuildCRIPlan(&params.CRI, cfg, o.PkgType)
b.AddResource("install.cri", instCriRsrc, plan.DependOn("install:config"))

instK8sRsrc := recipe.BuildK8SPlan(params.KubernetesVersion, params.KubeletConfig.NodeIP, cfg.SetSELinuxPermissive, cfg.DisableSwap, cfg.LockYUMPkgs, o.PkgType, params.KubeletConfig.CloudProvider)
instK8sRsrc := recipe.BuildK8SPlan(params.KubernetesVersion, params.KubeletConfig.NodeIP, cfg.SELinuxInstalled, cfg.SetSELinuxPermissive, cfg.DisableSwap, cfg.LockYUMPkgs, o.PkgType, params.KubeletConfig.CloudProvider)

b.AddResource("install:k8s", instK8sRsrc, plan.DependOn("install.cri"))

Expand Down
24 changes: 21 additions & 3 deletions pkg/plan/recipe/install_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,13 @@ func BuildCRIPlan(criSpec *baremetalspecv1.ContainerRuntime, cfg *envcfg.EnvSpec
log.Fatalf("Unknown CRI - %s", criSpec.Kind)
}

IsDockerOnCentOS := false
// Docker runtime
switch pkgType {
case resource.PkgTypeRPM, resource.PkgTypeRHEL:
b.AddResource("install:docker", &resource.RPM{Name: criSpec.Package, Version: criSpec.Version})
// SELinux will be here along with docker and containerd-selinux packages
IsDockerOnCentOS = true
case resource.PkgTypeDeb:
// TODO(michal): Use the official docker.com repo
b.AddResource("install:docker", &resource.Deb{Name: "docker.io"})
Expand All @@ -105,6 +108,20 @@ func BuildCRIPlan(criSpec *baremetalspecv1.ContainerRuntime, cfg *envcfg.EnvSpec
plan.DependOn("install:docker"))
}

// this is a special case: if SELinux is not there on RH, CentOS Linux family
// installing Docker will also installing SELinux
// then we set SELinux mode to be permissive right after the docker installation step
if IsDockerOnCentOS && cfg.SetSELinuxPermissive {
b.AddResource(
"selinux:permissive",
&resource.Run{
Script: object.String("setenforce 0 && sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config"),
// sometime, SELinux not installed yet so || true to ignore the error
UndoScript: object.String("setenforce 1 && sed -i 's/^SELINUX=permissive$/SELINUX=enforcing/' /etc/selinux/config || true"),
},
plan.DependOn("install:docker"))
}

b.AddResource(
"systemd:daemon-reload",
&resource.Run{Script: object.String("systemctl daemon-reload")},
Expand All @@ -114,6 +131,7 @@ func BuildCRIPlan(criSpec *baremetalspecv1.ContainerRuntime, cfg *envcfg.EnvSpec
"service-init:docker-service",
&resource.Service{Name: "docker", Status: "active", Enabled: true},
plan.DependOn("systemd:daemon-reload"))

p, err := b.Plan()

p.SetUndoCondition(func(r plan.Runner, _ plan.State) bool {
Expand All @@ -135,7 +153,7 @@ ExecStartPre=-/sbin/swapoff -a
`

// BuildK8SPlan creates a plan for running kubernetes on a node
func BuildK8SPlan(kubernetesVersion string, kubeletNodeIP string, setSELinuxPermissive, disableSwap, lockYUMPkgs bool, pkgType resource.PkgType, cloudProvider string) plan.Resource {
func BuildK8SPlan(kubernetesVersion string, kubeletNodeIP string, seLinuxInstalled, setSELinuxPermissive, disableSwap, lockYUMPkgs bool, pkgType resource.PkgType, cloudProvider string) plan.Resource {
b := plan.NewBuilder()

// Kubernetes repos
Expand All @@ -159,8 +177,8 @@ func BuildK8SPlan(kubernetesVersion string, kubeletNodeIP string, setSELinuxPerm
}, plan.DependOn("configure:kubernetes-repo-key"))
}

// Set SELinux to permissive mode.
if setSELinuxPermissive {
// If SELinux is already installed and we need to set SELinux to permissive mode, do it
if seLinuxInstalled && setSELinuxPermissive {
b.AddResource(
"selinux:permissive",
&resource.Run{
Expand Down
73 changes: 68 additions & 5 deletions pkg/plan/resource/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,51 @@ type OS struct {
factsGathered bool
}

type SELinuxStatus int

const (
SELinuxUnknown SELinuxStatus = iota
SELinuxNotInstalled
SELinuxInstalled
)

func (s SELinuxStatus) IsUnknown() bool {
return s == SELinuxUnknown
}

func (s SELinuxStatus) IsNotInstalled() bool {
return s == SELinuxNotInstalled
}

func (s SELinuxStatus) IsInstalled() bool {
return s == SELinuxInstalled
}

type SELinuxMode int

const (
SELinuxModeUnknown SELinuxMode = iota
SELinuxEnforcing
SELinuxPermissive
SELinuxDisabled
)

func (m SELinuxMode) IsUnknown() bool {
return m == SELinuxModeUnknown
}

func (m SELinuxMode) IsEnforcing() bool {
return m == SELinuxEnforcing
}

func (m SELinuxMode) IsPermissive() bool {
return m == SELinuxPermissive
}

func (m SELinuxMode) IsDisabled() bool {
return m == SELinuxDisabled
}

func NewOS(r plan.Runner) (*OS, error) {
osr := &OS{runner: r}
_, err := osr.Apply(r, plan.EmptyDiff())
Expand Down Expand Up @@ -163,25 +208,43 @@ func (p *OS) HasCommand(cmd string) (bool, error) {
return false, err
}

func (p *OS) HasSELinuxEnabled() (bool, error) {
func (p *OS) GetSELinuxStatus() (SELinuxStatus, SELinuxMode, error) {
const cmd = "selinuxenabled"

if hasCmd, err := p.HasCommand(cmd); err != nil {
// Inconclusive.
return false, err
return SELinuxUnknown, SELinuxModeUnknown, err
} else if !hasCmd {
// No SELinux tools installed.
return false, nil
return SELinuxNotInstalled, SELinuxModeUnknown, nil
}

if _, err := p.runner.RunCommand(cmd, nil); err == nil {
// SELinux not disabled (that is, enforcing or permissive).
return true, nil
// return SELinuxEnforcing, nil
if permissive, err := p.IsSELinuxMode("permissive"); err == nil && permissive {
return SELinuxInstalled, SELinuxPermissive, nil
} else if enforcing, err := p.IsSELinuxMode("enforcing"); err == nil && enforcing {
return SELinuxInstalled, SELinuxEnforcing, nil
} else {
return SELinuxInstalled, SELinuxModeUnknown, err
}
} else if err, ok := err.(*plan.RunError); ok && err.ExitCode == 1 {
// SELinux disabled.
return false, nil
return SELinuxInstalled, SELinuxDisabled, nil
} else {
// Inconclusive.
return SELinuxInstalled, SELinuxModeUnknown, err
}
}

func (p *OS) IsSELinuxMode(mode string) (bool, error) {
if _, err := p.runner.RunCommand("sestatus | grep 'Current mode' | grep "+mode, nil); err == nil {
return true, nil
} else if err, ok := err.(*plan.RunError); ok && err.ExitCode == 1 {
// selinux not in the permissive mode
return false, nil
} else {
return false, err
}
}
Expand Down
Loading

0 comments on commit 064057d

Please sign in to comment.