Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for annotation-based exemptions #227

Merged
merged 4 commits into from
Dec 6, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions examples/config-full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ security:
warning:
ifAnyAddedBeyond:
- NONE
controllers_to_scan:
- Deployments
- StatefulSets
- DaemonSets
- CronJobs
- Jobs
- ReplicationControllers
exemptions:
- controllerNames:
- dns-controller
Expand Down
13 changes: 13 additions & 0 deletions pkg/validator/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@
package validator

import (
"strings"

conf "github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/kube"
"github.com/fairwindsops/polaris/pkg/validator/controllers"
controller "github.com/fairwindsops/polaris/pkg/validator/controllers"
"github.com/sirupsen/logrus"
)

const exemptionAnnotationKey = "polaris.fairwinds.com/exempt"

// ValidateController validates a single controller, returns a ControllerResult.
func ValidateController(conf conf.Configuration, controller controller.Interface) ControllerResult {
controllerType := controller.GetType()
Expand All @@ -44,6 +48,9 @@ func ValidateControllers(config conf.Configuration, kubeResources *kube.Resource
}

for _, controller := range controllersToAudit {
if !config.DisallowExemptions && hasExemptionAnnotation(controller) {
continue
}
controllerResult := ValidateController(config, controller)
nsResult := nsResults.getNamespaceResult(controller.GetNamespace())
nsResult.Summary.appendResults(*controllerResult.PodResult.Summary)
Expand All @@ -52,3 +59,9 @@ func ValidateControllers(config conf.Configuration, kubeResources *kube.Resource
}
}
}

func hasExemptionAnnotation(ctrl controller.Interface) bool {
annot := ctrl.GetAnnotations()
val := annot[exemptionAnnotationKey]
return strings.ToLower(val) == "true"
}
49 changes: 46 additions & 3 deletions pkg/validator/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ package validator
import (
"testing"

conf "github.com/fairwindsops/polaris/pkg/config"
controller "github.com/fairwindsops/polaris/pkg/validator/controllers"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"

conf "github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/kube"
controller "github.com/fairwindsops/polaris/pkg/validator/controllers"
"github.com/fairwindsops/polaris/test"
"github.com/stretchr/testify/assert"
)

func TestValidateController(t *testing.T) {
Expand Down Expand Up @@ -134,3 +136,44 @@ func TestSkipHealthChecks(t *testing.T) {
assert.EqualValues(t, &expectedSum, actualResult.PodResult.Summary)
assert.EqualValues(t, expectedMessages, actualResult.PodResult.ContainerResults[0].Messages)
}

func TestControllerExemptions(t *testing.T) {
c := conf.Configuration{
HealthChecks: conf.HealthChecks{
ReadinessProbeMissing: conf.SeverityError,
LivenessProbeMissing: conf.SeverityWarning,
},
ControllersToScan: []conf.SupportedController{
conf.Deployments,
},
}
resources := &kube.ResourceProvider{
Deployments: []appsv1.Deployment{test.MockDeploy()},
}

expectedSum := ResultSummary{
Totals: CountSummary{
Successes: uint(0),
Warnings: uint(1),
Errors: uint(1),
},
ByCategory: make(map[string]*CountSummary),
}
expectedSum.ByCategory["Health Checks"] = &CountSummary{
Successes: uint(0),
Warnings: uint(1),
Errors: uint(1),
}
nsResults := NamespacedResults{}
ValidateControllers(c, resources, &nsResults)
actualResult := nsResults[""].DeploymentResults[0]
assert.Equal(t, "Deployments", actualResult.Type)
assert.EqualValues(t, &expectedSum, actualResult.PodResult.Summary)

resources.Deployments[0].ObjectMeta.Annotations = map[string]string{
exemptionAnnotationKey: "true",
}
nsResults = NamespacedResults{}
ValidateControllers(c, resources, &nsResults)
assert.Equal(t, (*NamespaceResult)(nil), nsResults[""])
}
5 changes: 5 additions & 0 deletions pkg/validator/controllers/cronjob.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ func (c CronJobController) GetType() config.SupportedController {
return config.CronJobs
}

// GetAnnotations returns the controller's annotations
func (c CronJobController) GetAnnotations() map[string]string {
return c.K8SResource.ObjectMeta.Annotations
}

// NewCronJobController builds a new controller interface for Deployments
func NewCronJobController(originalDeploymentResource kubeAPIBatchV1beta1.CronJob) Interface {
controller := CronJobController{}
Expand Down
5 changes: 5 additions & 0 deletions pkg/validator/controllers/daemonset.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ func (d DaemonSetController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &d.K8SResource.Spec.Template.Spec
}

// GetAnnotations returns the controller's annotations
func (d DaemonSetController) GetAnnotations() map[string]string {
return d.K8SResource.ObjectMeta.Annotations
}

// GetType returns the supportedcontroller enum type
func (d DaemonSetController) GetType() config.SupportedController {
return config.DaemonSets
Expand Down
5 changes: 5 additions & 0 deletions pkg/validator/controllers/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ func (d DeploymentController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &d.K8SResource.Spec.Template.Spec
}

// GetAnnotations returns the controller's annotations
func (d DeploymentController) GetAnnotations() map[string]string {
return d.K8SResource.ObjectMeta.Annotations
}

// GetType returns the supportedcontroller enum type
func (d DeploymentController) GetType() config.SupportedController {
return config.Deployments
Expand Down
1 change: 1 addition & 0 deletions pkg/validator/controllers/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Interface interface {
GetPodTemplate() *kubeAPICoreV1.PodTemplateSpec
GetPodSpec() *kubeAPICoreV1.PodSpec
GetType() config.SupportedController
GetAnnotations() map[string]string
}

// GenericController is a base implementation with some free methods for inherited structs
Expand Down
5 changes: 5 additions & 0 deletions pkg/validator/controllers/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ func (j JobController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &j.K8SResource.Spec.Template.Spec
}

// GetAnnotations returns the controller's annotations
func (j JobController) GetAnnotations() map[string]string {
return j.K8SResource.ObjectMeta.Annotations
}

// GetType returns the supportedcontroller enum type
func (j JobController) GetType() config.SupportedController {
return config.Jobs
Expand Down
5 changes: 5 additions & 0 deletions pkg/validator/controllers/replicationcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ func (r ReplicationControllerController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &r.K8SResource.Spec.Template.Spec
}

// GetAnnotations returns the controller's annotations
func (r ReplicationControllerController) GetAnnotations() map[string]string {
return r.K8SResource.ObjectMeta.Annotations
}

// GetType returns the supportedcontroller enum type
func (r ReplicationControllerController) GetType() config.SupportedController {
return config.ReplicationControllers
Expand Down
5 changes: 5 additions & 0 deletions pkg/validator/controllers/statefulsets.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ func (s StatefulSetController) GetPodSpec() *kubeAPICoreV1.PodSpec {
return &s.K8SResource.Spec.Template.Spec
}

// GetAnnotations returns the controller's annotations
func (s StatefulSetController) GetAnnotations() map[string]string {
return s.K8SResource.ObjectMeta.Annotations
}

// GetType returns the supportedcontroller enum type
func (s StatefulSetController) GetType() config.SupportedController {
return config.StatefulSets
Expand Down