Files
polaris/pkg/validator/pod.go
Nick Huanca 4c7429efbc #146 Fixing Container Security Context Logic (#149)
* Fixing Container Security Context Logic

Kubernetes rationalizes Container Security Context in conjunction with the
Pod Spec Security Context. In this scenario you can 'leave out' certain
security context settings and rely on the pod spec definition to still
set these settings for you. The RunAsNonRoot setting originally only checked
to see if the value was set at the container level, vs also checking if it
was enabled at the pod level.

I have attached the container's parent pod spec to the container validate
struct in case any other things like this arise in the future.

I have also refactored the logic for validating bool pointers, since these
can be tricky, if you want to avoid dereferences pointer issues.

Changes:
- Added parent pod spec of container to validate certain settings which affect container spec
- Refactored the logic statements for validating bool pointers (used helpers)
- Added tests for this pod.container.securityContext condition
2019-06-18 11:04:38 -06:00

94 lines
2.8 KiB
Go

// Copyright 2019 ReactiveOps
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
conf "github.com/reactiveops/polaris/pkg/config"
"github.com/reactiveops/polaris/pkg/validator/messages"
corev1 "k8s.io/api/core/v1"
)
// PodValidation tracks validation failures associated with a Pod.
type PodValidation struct {
*ResourceValidation
Pod *corev1.PodSpec
}
// ValidatePod validates that each pod conforms to the Polaris config, returns a ResourceResult.
func ValidatePod(podConf conf.Configuration, pod *corev1.PodSpec) PodResult {
pv := PodValidation{
Pod: pod,
ResourceValidation: &ResourceValidation{},
}
pv.validateSecurity(&podConf.Security)
pv.validateNetworking(&podConf.Networking)
pRes := PodResult{
Messages: pv.messages(),
ContainerResults: []ContainerResult{},
Summary: pv.summary(),
podSpec: *pod,
}
pv.validateContainers(pod.InitContainers, &pRes, &podConf, true)
pv.validateContainers(pod.Containers, &pRes, &podConf, false)
for _, cRes := range pRes.ContainerResults {
pRes.Summary.appendResults(*cRes.Summary)
}
return pRes
}
func (pv *PodValidation) validateContainers(containers []corev1.Container, pRes *PodResult, podConf *conf.Configuration, isInit bool) {
for _, container := range containers {
cRes := ValidateContainer(&container, pRes, podConf, isInit)
pRes.ContainerResults = append(pRes.ContainerResults, cRes)
}
}
func (pv *PodValidation) validateSecurity(securityConf *conf.Security) {
category := messages.CategorySecurity
if securityConf.HostIPCSet.IsActionable() {
if pv.Pod.HostIPC {
pv.addFailure(messages.HostIPCFailure, securityConf.HostIPCSet, category)
} else {
pv.addSuccess(messages.HostIPCSuccess, category)
}
}
if securityConf.HostPIDSet.IsActionable() {
if pv.Pod.HostPID {
pv.addFailure(messages.HostPIDFailure, securityConf.HostPIDSet, category)
} else {
pv.addSuccess(messages.HostPIDSuccess, category)
}
}
}
func (pv *PodValidation) validateNetworking(networkConf *conf.Networking) {
category := messages.CategoryNetworking
if networkConf.HostNetworkSet.IsActionable() {
if pv.Pod.HostNetwork {
pv.addFailure(messages.HostNetworkFailure, networkConf.HostNetworkSet, category)
} else {
pv.addSuccess(messages.HostNetworkSuccess, category)
}
}
}