Skip to content

Commit

Permalink
Check for the recommended security requirements of the container-nati…
Browse files Browse the repository at this point in the history
…ve operators

checks:
USER id should not be 0

readOnlyRootFilesystem = true

runAsNonRoot = true

automount service account token = false{}
  • Loading branch information
shimritproj committed May 29, 2024
1 parent 592bc8d commit 1ec1c62
Show file tree
Hide file tree
Showing 16 changed files with 475 additions and 5 deletions.
72 changes: 68 additions & 4 deletions CATALOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Depending on the workload type, not all tests are required to pass to satisfy be

## Test cases summary

### Total test cases: 109
### Total test cases: 113

### Total suites: 10

Expand All @@ -19,7 +19,7 @@ Depending on the workload type, not all tests are required to pass to satisfy be
|manageability|2|
|networking|11|
|observability|4|
|operator|7|
|operator|11|
|performance|6|
|platform-alteration|13|
|preflight|17|
Expand All @@ -36,11 +36,11 @@ Depending on the workload type, not all tests are required to pass to satisfy be
|---|---|
|7|1|

### Non-Telco specific tests only: 62
### Non-Telco specific tests only: 66

|Mandatory|Optional|
|---|---|
|42|20|
|46|20|

### Telco specific tests only: 27

Expand Down Expand Up @@ -1122,6 +1122,22 @@ Tags|telco,observability

### operator

#### operator-automount-tokens

Property|Description
---|---
Unique ID|operator-automount-tokens
Description|Tests that checks the automount service account token is disabled.
Suggested Remediation|Ensure that the automount service account token is disabled.
Best Practice Reference|https://test-network-function.github.io/cnf-best-practices-guide/#cnf-best-practices-cnf-operator-requirements
Exception Process|No exceptions
Tags|common,operator
|**Scenario**|**Optional/Mandatory**|
|Extended|Mandatory|
|Far-Edge|Mandatory|
|Non-Telco|Mandatory|
|Telco|Mandatory|

#### operator-crd-openapi-schema

Property|Description
Expand Down Expand Up @@ -1202,6 +1218,54 @@ Tags|common,operator
|Non-Telco|Mandatory|
|Telco|Mandatory|

#### operator-read-only-file-system

Property|Description
---|---
Unique ID|operator-read-only-file-system
Description|Tests that checks the read-only root filesystem setting is enabled.
Suggested Remediation|Ensure that the read-only root filesystem setting is enabled.
Best Practice Reference|https://test-network-function.github.io/cnf-best-practices-guide/#cnf-best-practices-cnf-operator-requirements
Exception Process|No exceptions
Tags|common,operator
|**Scenario**|**Optional/Mandatory**|
|Extended|Mandatory|
|Far-Edge|Mandatory|
|Non-Telco|Mandatory|
|Telco|Mandatory|

#### operator-run-as-non-root

Property|Description
---|---
Unique ID|operator-run-as-non-root
Description|Tests that checks run as non root.
Suggested Remediation|Ensure that run as non root.
Best Practice Reference|https://test-network-function.github.io/cnf-best-practices-guide/#cnf-best-practices-cnf-operator-requirements
Exception Process|No exceptions
Tags|common,operator
|**Scenario**|**Optional/Mandatory**|
|Extended|Mandatory|
|Far-Edge|Mandatory|
|Non-Telco|Mandatory|
|Telco|Mandatory|

#### operator-run-as-user-id

Property|Description
---|---
Unique ID|operator-run-as-user-id
Description|Tests that checks user id should not be 0.
Suggested Remediation|Ensure that user id should not be 0.
Best Practice Reference|https://test-network-function.github.io/cnf-best-practices-guide/#cnf-best-practices-cnf-operator-requirements
Exception Process|No exceptions
Tags|common,operator
|**Scenario**|**Optional/Mandatory**|
|Extended|Mandatory|
|Far-Edge|Mandatory|
|Non-Telco|Mandatory|
|Telco|Mandatory|

#### operator-semantic-versioning

Property|Description
Expand Down
2 changes: 1 addition & 1 deletion cnf-certification-test/accesscontrol/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import (

"github.com/operator-framework/api/pkg/operators/v1alpha1"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/accesscontrol/namespace"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/accesscontrol/rbac"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/accesscontrol/resources"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/accesscontrol/securitycontextcontainer"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/common"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/common/rbac"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/identifiers"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/networking/netutil"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/networking/services"
Expand Down
File renamed without changes.
4 changes: 4 additions & 0 deletions cnf-certification-test/identifiers/doclinks.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ const (
TestOperatorCrdSchemaIdentifierDocLink = DocOperatorRequirement
TestOperatorCrdVersioningIdentifierDocLink = DocOperatorRequirement
TestOperatorSingleCrdOwnerIdentifierDocLink = DocOperatorRequirement
TestOperatorRunAsUserIDDocLink = DocOperatorRequirement
TestOperatorRunAsNonRootDocLink = DocOperatorRequirement
TestOperatorAutomountTokensDocLink = DocOperatorRequirement
TestOperatorReadOnlyFilesystemDocLink = DocOperatorRequirement

// Observability Test Suite
TestLoggingIdentifierDocLink = "https://test-network-function.github.io/cnf-best-practices-guide/#cnf-best-practices-logging"
Expand Down
68 changes: 68 additions & 0 deletions cnf-certification-test/identifiers/identifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ var (
TestHelmIsCertifiedIdentifier claim.Identifier
TestOperatorIsInstalledViaOLMIdentifier claim.Identifier
TestOperatorHasSemanticVersioningIdentifier claim.Identifier
TestOperatorReadOnlyFilesystem claim.Identifier
TestOperatorAutomountTokens claim.Identifier
TestOperatorRunAsNonRoot claim.Identifier
TestOperatorRunAsUserID claim.Identifier
TestOperatorCrdVersioningIdentifier claim.Identifier
TestOperatorCrdSchemaIdentifier claim.Identifier
TestOperatorSingleCrdOwnerIdentifier claim.Identifier
Expand Down Expand Up @@ -930,6 +934,70 @@ that Node's kernel may not have the same hacks.'`,
},
TagCommon)

TestOperatorRunAsUserID = AddCatalogEntry(
"run-as-user-id",
common.OperatorTestKey,
`Tests that checks user id should not be 0.`,
OperatorRunAsUserID,
NoExceptions,
TestOperatorRunAsUserIDDocLink,
true,
map[string]string{
FarEdge: Mandatory,
Telco: Mandatory,
NonTelco: Mandatory,
Extended: Mandatory,
},
TagCommon)

TestOperatorRunAsNonRoot = AddCatalogEntry(
"run-as-non-root",
common.OperatorTestKey,
`Tests that checks run as non root.`,
OperatorRunAsNonRoot,
NoExceptions,
TestOperatorRunAsNonRootDocLink,
true,
map[string]string{
FarEdge: Mandatory,
Telco: Mandatory,
NonTelco: Mandatory,
Extended: Mandatory,
},
TagCommon)

TestOperatorAutomountTokens = AddCatalogEntry(
"automount-tokens",
common.OperatorTestKey,
`Tests that checks the automount service account token is disabled.`,
OperatorAutomountTokens,
NoExceptions,
TestOperatorAutomountTokensDocLink,
true,
map[string]string{
FarEdge: Mandatory,
Telco: Mandatory,
NonTelco: Mandatory,
Extended: Mandatory,
},
TagCommon)

TestOperatorReadOnlyFilesystem = AddCatalogEntry(
"read-only-file-system",
common.OperatorTestKey,
`Tests that checks the read-only root filesystem setting is enabled.`,
OperatorReadOnlyFilesystem,
NoExceptions,
TestOperatorReadOnlyFilesystemDocLink,
true,
map[string]string{
FarEdge: Mandatory,
Telco: Mandatory,
NonTelco: Mandatory,
Extended: Mandatory,
},
TagCommon)

TestOperatorCrdVersioningIdentifier = AddCatalogEntry(
"crd-versioning",
common.OperatorTestKey,
Expand Down
8 changes: 8 additions & 0 deletions cnf-certification-test/identifiers/remediation.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ const (

OperatorCrdSchemaIdentifierRemediation = `Ensure that the Operator CRD is defined with OpenAPI spec.`

OperatorRunAsUserID = `Ensure that user id should not be 0.`

OperatorRunAsNonRoot = `Ensure that run as non root.`

OperatorAutomountTokens = `Ensure that the automount service account token is disabled.`

OperatorReadOnlyFilesystem = `Ensure that the read-only root filesystem setting is enabled.`

OperatorCrdVersioningRemediation = `Ensure that the Operator CRD has a valid version.`

OperatorSingleCrdOwnerRemediation = `Ensure that a CRD is owned by only one Operator`
Expand Down
138 changes: 138 additions & 0 deletions cnf-certification-test/operator/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
package operator

import (
"fmt"
"strings"

"github.com/test-network-function/cnf-certification-test/cnf-certification-test/common"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/common/rbac"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/identifiers"
"github.com/test-network-function/cnf-certification-test/cnf-certification-test/operator/phasecheck"
"github.com/test-network-function/cnf-certification-test/internal/clientsholder"

"github.com/test-network-function/cnf-certification-test/internal/log"
"github.com/test-network-function/cnf-certification-test/pkg/checksdb"
Expand All @@ -39,6 +42,7 @@ var (
}
)

//nolint:funlen
func LoadChecks() {
log.Debug("Loading %s suite checks", common.OperatorTestKey)

Expand Down Expand Up @@ -93,6 +97,33 @@ func LoadChecks() {
testOperatorSingleCrdOwner(c, &env)
return nil
}))

checksGroup.Add(checksdb.NewCheck(identifiers.GetTestIDAndLabels(identifiers.TestOperatorRunAsUserID)).
WithSkipCheckFn(testhelper.GetNoOperatorsSkipFn(&env)).
WithCheckFn(func(c *checksdb.Check) error {
testOperatorRunAsUserID(c, &env)
return nil
}))
checksGroup.Add(checksdb.NewCheck(identifiers.GetTestIDAndLabels(identifiers.TestOperatorRunAsNonRoot)).
WithSkipCheckFn(testhelper.GetNoOperatorsSkipFn(&env)).
WithCheckFn(func(c *checksdb.Check) error {
testOperatorRunAsNonRoot(c, &env)
return nil
}))

checksGroup.Add(checksdb.NewCheck(identifiers.GetTestIDAndLabels(identifiers.TestOperatorAutomountTokens)).
WithSkipCheckFn(testhelper.GetNoOperatorsSkipFn(&env)).
WithCheckFn(func(c *checksdb.Check) error {
testOperatorAutomountTokens(c, &env)
return nil
}))

checksGroup.Add(checksdb.NewCheck(identifiers.GetTestIDAndLabels(identifiers.TestOperatorReadOnlyFilesystem)).
WithSkipCheckFn(testhelper.GetNoOperatorsSkipFn(&env)).
WithCheckFn(func(c *checksdb.Check) error {
testOperatorReadOnlyFilesystem(c, &env)
return nil
}))
}

// This function check if the Operator CRD version follows K8s versioning
Expand Down Expand Up @@ -318,3 +349,110 @@ func testOperatorSingleCrdOwner(check *checksdb.Check, env *provider.TestEnviron

check.SetResult(compliantObjects, nonCompliantObjects)
}

func testOperatorRunAsUserID(check *checksdb.Check, env *provider.TestEnvironment) {
var compliantObjects []*testhelper.ReportObject
var nonCompliantObjects []*testhelper.ReportObject
for i := range env.Operators {
operator := env.Operators[i]
check.LogInfo("Testing Operator %q", operator)
AllPods := findAllPods(env, operator)
for _, put := range AllPods {
check.LogInfo("Testing Pod %q", put)
if put.IsRunAsUserID(0) {
check.LogError("Pod %q UserID is 0", put.Name)
nonCompliantObjects = append(nonCompliantObjects, testhelper.NewPodReportObject(put.Namespace, put.Name, "Pod has been found with UserID is 0", false))
} else {
check.LogInfo("Pod %q UserID is not 0", put.Name)
compliantObjects = append(compliantObjects, testhelper.NewPodReportObject(put.Namespace, put.Name, "Pod has been found with UserID is not 0", true))
}
}
}
check.SetResult(compliantObjects, nonCompliantObjects)
}

func testOperatorRunAsNonRoot(check *checksdb.Check, env *provider.TestEnvironment) {
var compliantObjects []*testhelper.ReportObject
var nonCompliantObjects []*testhelper.ReportObject
for i := range env.Operators {
operator := env.Operators[i]
check.LogInfo("Testing Operator %q", operator)
AllPods := findAllPods(env, operator)
for _, put := range AllPods {
check.LogInfo("Testing Pod %q", put)
if put.IsRunAsNonRoot() {
check.LogInfo("Pod %q is run as not root", put.Name)
compliantObjects = append(compliantObjects, testhelper.NewPodReportObject(put.Namespace, put.Name, "Pod has been found is run as not root", true))
} else {
check.LogError("Pod %q is run as root", put.Name)
nonCompliantObjects = append(nonCompliantObjects, testhelper.NewPodReportObject(put.Namespace, put.Name, "Pod has been found is run as root", false))
}
}
}
check.SetResult(compliantObjects, nonCompliantObjects)
}

func testOperatorAutomountTokens(check *checksdb.Check, env *provider.TestEnvironment) {
var compliantObjects []*testhelper.ReportObject
var nonCompliantObjects []*testhelper.ReportObject
for i := range env.Operators {
operator := env.Operators[i]
check.LogInfo("Testing Operator %q", operator)
AllPods := findAllPods(env, operator)
for _, put := range AllPods {
check.LogInfo("Testing Pod %q", put)
// Evaluate the pod's automount service tokens and any attached service accounts
client := clientsholder.GetClientsHolder()
podPassed, newMsg := rbac.EvaluateAutomountTokens(client.K8sClient.CoreV1(), put.Pod)
if !podPassed {
check.LogInfo("Pod %q have automount service tokens set to false", put)
compliantObjects = append(compliantObjects, testhelper.NewPodReportObject(put.Namespace, put.Name, "Pod %q have automount service tokens set to false", true))
} else {
check.LogError(newMsg)
nonCompliantObjects = append(nonCompliantObjects, testhelper.NewPodReportObject(put.Namespace, put.Name, newMsg, false))
}
}
}
check.SetResult(compliantObjects, nonCompliantObjects)
}

func testOperatorReadOnlyFilesystem(check *checksdb.Check, env *provider.TestEnvironment) {
var compliantObjects []*testhelper.ReportObject
var nonCompliantObjects []*testhelper.ReportObject
for i := range env.Operators {
operator := env.Operators[i]
check.LogInfo("Testing Operator %q", operator)
AllPods := findAllPods(env, operator)
for _, put := range AllPods {
check.LogInfo("Testing Pod %q", put)
for _, cut := range put.Containers {
check.LogInfo("Testing Container %q", cut.Name)
if cut.IsReadOnlyRootFilesystem(check.GetLoggger()) {
check.LogInfo("Pod %q container %q is read only root file system.", put.Name, cut.Name)
compliantObjects = append(compliantObjects, testhelper.NewPodReportObject(put.Namespace, put.Name, "Pod has been found read only root file system", true))
} else {
check.LogError("Pod %q container %q is read not only root file system.", put.Name, cut.Name)
nonCompliantObjects = append(nonCompliantObjects, testhelper.NewPodReportObject(put.Namespace, put.Name, "Pod has been found read not only root file system", false))
}
}
}
}
check.SetResult(compliantObjects, nonCompliantObjects)
}

func findAllPods(env *provider.TestEnvironment, operator *provider.Operator) []*provider.Pod {
var AllPods []*provider.Pod
for _, put := range env.AllPods {
fmt.Printf("pod: %v", put)
for _, ownerRef := range put.ObjectMeta.GetOwnerReferences() {
for i := range operator.Csv.Spec.CustomResourceDefinitions.Owned {
ownerRefOperator := operator.Csv.Spec.CustomResourceDefinitions.Owned[i]
if ownerRef.Kind == ownerRefOperator.Kind && ownerRef.Name == ownerRefOperator.Name {
AllPods = append(AllPods, put)
break
}
}
}
}
return AllPods
}
Loading

0 comments on commit 1ec1c62

Please sign in to comment.