mirror of
https://github.com/FairwindsOps/polaris.git
synced 2026-05-22 00:54:06 +00:00
security validation fixes and more thorough tests
This commit is contained in:
@@ -226,12 +226,13 @@ func (cv *ContainerValidation) validateCapabilities(confLists conf.SecurityCapab
|
||||
}
|
||||
|
||||
if len(confLists.IfAnyNotDropped) > 0 {
|
||||
intersectDrops := capIntersection(capabilities.Drop, confLists.IfAnyNotDropped)
|
||||
if len(intersectDrops) > 0 && !capContains(capabilities.Drop, "ALL") {
|
||||
capsString := commaSeparatedCapabilities(intersectDrops)
|
||||
missingDrops := capDifference(confLists.IfAnyNotDropped, capabilities.Drop)
|
||||
|
||||
if len(missingDrops) > 0 && !capContains(capabilities.Drop, "ALL") {
|
||||
capsString := commaSeparatedCapabilities(missingDrops)
|
||||
cv.addFailure(fmt.Sprintf("Security capabilities not dropped from %v list: %v", severity, capsString), severity)
|
||||
} else {
|
||||
cv.addSuccess(fmt.Sprintf("All security capabilities dropped from %v list", severity))
|
||||
cv.addSuccess(fmt.Sprintf("Required security capabilities dropped from %v list", severity))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,6 +352,21 @@ func TestValidateSecurity(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
strongConf := conf.Security{
|
||||
RunAsRootAllowed: conf.SeverityError,
|
||||
RunAsPrivileged: conf.SeverityError,
|
||||
NotReadOnlyRootFileSystem: conf.SeverityError,
|
||||
PrivilegeEscalationAllowed: conf.SeverityError,
|
||||
Capabilities: conf.SecurityCapabilities{
|
||||
Error: conf.SecurityCapabilityLists{
|
||||
IfAnyAdded: []corev1.Capability{"ALL", "SYS_ADMIN", "NET_ADMIN"},
|
||||
IfAnyNotDropped: []corev1.Capability{"NET_BIND_SERVICE", "DAC_OVERRIDE", "SYS_CHROOT"},
|
||||
},
|
||||
Warning: conf.SecurityCapabilityLists{
|
||||
IfAnyAddedBeyond: []corev1.Capability{"NONE"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
emptyCV := ContainerValidation{
|
||||
Container: &corev1.Container{Name: ""},
|
||||
@@ -376,6 +391,21 @@ func TestValidateSecurity(t *testing.T) {
|
||||
}
|
||||
|
||||
goodCV := ContainerValidation{
|
||||
Container: &corev1.Container{Name: "", SecurityContext: &corev1.SecurityContext{
|
||||
RunAsNonRoot: &trueVar,
|
||||
ReadOnlyRootFilesystem: &trueVar,
|
||||
Privileged: &falseVar,
|
||||
AllowPrivilegeEscalation: &falseVar,
|
||||
Capabilities: &corev1.Capabilities{
|
||||
Drop: []corev1.Capability{"NET_BIND_SERVICE", "FOWNER"},
|
||||
},
|
||||
}},
|
||||
ResourceValidation: &ResourceValidation{
|
||||
Summary: &ResultSummary{},
|
||||
},
|
||||
}
|
||||
|
||||
strongCV := ContainerValidation{
|
||||
Container: &corev1.Container{Name: "", SecurityContext: &corev1.SecurityContext{
|
||||
RunAsNonRoot: &trueVar,
|
||||
ReadOnlyRootFilesystem: &trueVar,
|
||||
@@ -474,13 +504,75 @@ func TestValidateSecurity(t *testing.T) {
|
||||
Type: "success",
|
||||
}},
|
||||
},
|
||||
{
|
||||
name: "good security context + strong validation config",
|
||||
securityConf: strongConf,
|
||||
cv: goodCV,
|
||||
expectedMessages: []*ResultMessage{{
|
||||
Message: "Security capabilities not dropped from error list: DAC_OVERRIDE, SYS_CHROOT",
|
||||
Type: "error",
|
||||
}, {
|
||||
Message: "Container is not allowed to run as root",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "Container is running with a read only filesystem",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "Container is not running as privileged",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "Container does not allow privilege escalation",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "No security capabilities added from error list",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "No security capabilities added beyond warning list",
|
||||
Type: "success",
|
||||
}},
|
||||
},
|
||||
{
|
||||
name: "strong security context + strong validation config",
|
||||
securityConf: strongConf,
|
||||
cv: strongCV,
|
||||
expectedMessages: []*ResultMessage{{
|
||||
Message: "Container is not allowed to run as root",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "Container is running with a read only filesystem",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "Container is not running as privileged",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "Container does not allow privilege escalation",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "No security capabilities added from error list",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "Required security capabilities dropped from error list",
|
||||
Type: "success",
|
||||
}, {
|
||||
Message: "No security capabilities added beyond warning list",
|
||||
Type: "success",
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.cv = resetCV(tt.cv)
|
||||
tt.cv.validateSecurity(&tt.securityConf)
|
||||
assert.Len(t, tt.cv.messages(), len(tt.expectedMessages))
|
||||
assert.ElementsMatch(t, tt.cv.messages(), tt.expectedMessages)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func resetCV(cv ContainerValidation) ContainerValidation {
|
||||
cv.Errors = []*ResultMessage{}
|
||||
cv.Successes = []*ResultMessage{}
|
||||
cv.Warnings = []*ResultMessage{}
|
||||
return cv
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user