Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6cf2d17
feat: add support any kinds for policy checks
afdesk Aug 6, 2025
d8a81cc
Merge branch 'main' of github.com:afdesk/trivy-operator into feat/cus…
afdesk Aug 19, 2025
acdb9db
fix: use a correct package for slices
afdesk Aug 19, 2025
ab3a423
refactor: improve kind selection
afdesk Aug 20, 2025
56d3c0f
feat: add namespaced resource detection
afdesk Aug 20, 2025
344da7e
refactor: use scopeResolver to detect cluster-scope resources
afdesk Aug 21, 2025
df7042a
test: remove deprecared use-case
afdesk Aug 21, 2025
dfae3da
refactor: rename a variable
afdesk Aug 21, 2025
532d6ad
Merge branch 'main' of github.com:afdesk/trivy-operator into feat/cus…
afdesk Aug 21, 2025
f08123f
chore: create reconcilers for every resource
afdesk Aug 21, 2025
6b3047b
refactor: integrate k8s scope resolver into object resolver
afdesk Aug 22, 2025
15c4ab9
refactor: integrate k8s scope resolve into NewObjectResolver
afdesk Aug 22, 2025
884c7fc
fix: don't add Ingress for every workloads
afdesk Aug 25, 2025
01af588
refactor: use prepare method for GVK
afdesk Aug 25, 2025
97223be
test: add unit-tests for K8sScopeResolver
afdesk Aug 25, 2025
5eb2097
fix: linter error
afdesk Aug 25, 2025
37dd96d
test: add integration test cases for PV and PVC
afdesk Aug 25, 2025
445eae3
chore: update GetTargetWorkloads
afdesk Aug 25, 2025
073e163
Update pkg/kube/object.go
simar7 Aug 25, 2025
96614a5
test: add a case when PVC is disabled
afdesk Aug 27, 2025
118e408
Merge branch 'feat/custom-resources' of github.com:afdesk/trivy-opera…
afdesk Aug 27, 2025
8550536
chore: fix golang linter issues
afdesk Aug 27, 2025
53eb3d3
Merge branch 'main' of github.com:afdesk/trivy-operator into feat/cus…
afdesk Sep 3, 2025
7281b75
fix: add needed data for integration tests
afdesk Sep 3, 2025
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
8 changes: 7 additions & 1 deletion pkg/configauditreport/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type ReportBuilder struct {
resourceLabelsToInclude []string
additionalReportLabels labels.Set
etc.Config
scopeResolver *kube.K8sScope
}

func NewReportBuilder(scheme *runtime.Scheme) *ReportBuilder {
Expand All @@ -38,6 +39,11 @@ func NewReportBuilder(scheme *runtime.Scheme) *ReportBuilder {
}
}

func (b *ReportBuilder) ScopeResolver(sr *kube.K8sScope) *ReportBuilder {
b.scopeResolver = sr
return b
}

func (b *ReportBuilder) Controller(controller client.Object) *ReportBuilder {
b.controller = controller
return b
Expand Down Expand Up @@ -170,7 +176,7 @@ func (b *ReportBuilder) GetReport() (v1alpha1.ConfigAuditReport, error) {
}

func (b *ReportBuilder) Write(ctx context.Context, writer Writer) error {
if kube.IsClusterScopedKind(b.controller.GetObjectKind().GroupVersionKind().Kind) {
if b.scopeResolver != nil && b.scopeResolver.IsClusterScope(b.controller.GetObjectKind().GroupVersionKind().Kind) {
report, err := b.GetClusterReport()
if err != nil {
return err
Expand Down
1 change: 1 addition & 0 deletions pkg/configauditreport/controller/nodecollector.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ func (r *NodeCollectorJobController) processCompleteScanJob(ctx context.Context,
return fmt.Errorf("failed to evaluate policies on Node : %w", err)
}
infraReportBuilder := infraassessment.NewReportBuilder(r.Client.Scheme()).
ScopeResolver(&r.ObjectResolver.K8sScope).
Controller(node).
ResourceSpecHash(resourceHash).
PluginConfigHash(policiesHash).
Expand Down
36 changes: 3 additions & 33 deletions pkg/configauditreport/controller/policyconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ import (

"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -41,32 +38,14 @@ type PolicyConfigController struct {

// Controller for trivy-operator-policies-config in the operator namespace; must be cluster scoped even with namespace predicate
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch

func (r *PolicyConfigController) SetupWithManager(mgr ctrl.Manager) error {

// Determine which Kubernetes workloads the controller will reconcile and add them to resources
targetWorkloads := r.Config.GetTargetWorkloads()
workloadResources := make([]kube.Resource, 0)
for _, tw := range targetWorkloads {
var resource kube.Resource
if err := resource.GetWorkloadResource(tw, &v1alpha1.ConfigAuditReport{}, r.ObjectResolver); err != nil {
return err
}
workloadResources = append(workloadResources, resource)
}

// Add non workload related resources
resources := []kube.Resource{
{Kind: kube.KindService, ForObject: &corev1.Service{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
{Kind: kube.KindConfigMap, ForObject: &corev1.ConfigMap{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
{Kind: kube.KindRole, ForObject: &rbacv1.Role{}, OwnsObject: &v1alpha1.RbacAssessmentReport{}},
{Kind: kube.KindRoleBinding, ForObject: &rbacv1.RoleBinding{}, OwnsObject: &v1alpha1.RbacAssessmentReport{}},
{Kind: kube.KindNetworkPolicy, ForObject: &networkingv1.NetworkPolicy{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
{Kind: kube.KindResourceQuota, ForObject: &corev1.ResourceQuota{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
{Kind: kube.KindLimitRange, ForObject: &corev1.LimitRange{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
resources, clusterResources, err := kube.GetActiveResource(targetWorkloads, r.ObjectResolver, r.Scheme())
if err != nil {
return fmt.Errorf("unable to setup resources for PolicyConfigController: %w", err)
}

resources = append(resources, workloadResources...)
for _, configResource := range resources {
if err := ctrl.NewControllerManagedBy(mgr).
For(&corev1.ConfigMap{}, builder.WithPredicates(
Expand All @@ -77,13 +56,6 @@ func (r *PolicyConfigController) SetupWithManager(mgr ctrl.Manager) error {
Complete(r.reconcileConfig(configResource.Kind)); err != nil {
return fmt.Errorf("constructing controller for %s: %w", configResource.Kind, err)
}

}

clusterResources := []kube.Resource{
{Kind: kube.KindClusterRole, ForObject: &rbacv1.ClusterRole{}, OwnsObject: &v1alpha1.ClusterRbacAssessmentReport{}},
{Kind: kube.KindClusterRoleBindings, ForObject: &rbacv1.ClusterRoleBinding{}, OwnsObject: &v1alpha1.ClusterRbacAssessmentReport{}},
{Kind: kube.KindCustomResourceDefinition, ForObject: &apiextensionsv1.CustomResourceDefinition{}, OwnsObject: &v1alpha1.ClusterConfigAuditReport{}},
}

for _, resource := range clusterResources {
Expand All @@ -97,9 +69,7 @@ func (r *PolicyConfigController) SetupWithManager(mgr ctrl.Manager) error {
return err
}
}

return nil

}

func (r *PolicyConfigController) reconcileConfig(kind kube.Kind) reconcile.Func {
Expand Down
47 changes: 11 additions & 36 deletions pkg/configauditreport/controller/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ import (
"time"

"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/errors"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
Expand Down Expand Up @@ -88,13 +84,13 @@ func (r *ResourceController) SetupWithManager(mgr ctrl.Manager) error {

// Determine which Kubernetes workloads the controller will reconcile and add them to resources
targetWorkloads := r.Config.GetTargetWorkloads()
targetWorkloads = append(targetWorkloads, strings.ToLower(string(kube.KindIngress)))
for _, tw := range targetWorkloads {
var resource kube.Resource
err = resource.GetWorkloadResource(tw, &v1alpha1.ConfigAuditReport{}, r.ObjectResolver)
if err != nil {
return err
}

resources, clusterResources, err := kube.GetActiveResource(targetWorkloads, r.ObjectResolver, r.Scheme())
if err != nil {
return fmt.Errorf("unable to setup resources for ResourceController: %w", err)
}

for _, resource := range resources {
resourceBuilder := r.buildControlMgr(mgr, resource, installModePredicate)
if r.Config.InfraAssessmentScannerEnabled {
resourceBuilder.Owns(&v1alpha1.InfraAssessmentReport{})
Expand All @@ -104,30 +100,6 @@ func (r *ResourceController) SetupWithManager(mgr ctrl.Manager) error {
}
}

// Add non workload related resources
resources := []kube.Resource{
{Kind: kube.KindService, ForObject: &corev1.Service{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
{Kind: kube.KindConfigMap, ForObject: &corev1.ConfigMap{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
{Kind: kube.KindRole, ForObject: &rbacv1.Role{}, OwnsObject: &v1alpha1.RbacAssessmentReport{}},
{Kind: kube.KindRoleBinding, ForObject: &rbacv1.RoleBinding{}, OwnsObject: &v1alpha1.RbacAssessmentReport{}},
{Kind: kube.KindNetworkPolicy, ForObject: &networkingv1.NetworkPolicy{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
{Kind: kube.KindResourceQuota, ForObject: &corev1.ResourceQuota{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
{Kind: kube.KindLimitRange, ForObject: &corev1.LimitRange{}, OwnsObject: &v1alpha1.ConfigAuditReport{}},
}

for _, configResource := range resources {
if err := r.buildControlMgr(mgr, configResource, installModePredicate).
Complete(r.reconcileResource(configResource.Kind)); err != nil {
return fmt.Errorf("constructing controller for %s: %w", configResource.Kind, err)
}
}

clusterResources := []kube.Resource{
{Kind: kube.KindClusterRole, ForObject: &rbacv1.ClusterRole{}, OwnsObject: &v1alpha1.ClusterRbacAssessmentReport{}},
{Kind: kube.KindClusterRoleBindings, ForObject: &rbacv1.ClusterRoleBinding{}, OwnsObject: &v1alpha1.ClusterRbacAssessmentReport{}},
{Kind: kube.KindCustomResourceDefinition, ForObject: &apiextensionsv1.CustomResourceDefinition{}, OwnsObject: &v1alpha1.ClusterConfigAuditReport{}},
}

for _, resource := range clusterResources {
if err = ctrl.NewControllerManagedBy(mgr).WithOptions(controller.Options{
CacheSyncTimeout: r.CacheSyncTimeout,
Expand Down Expand Up @@ -246,6 +218,7 @@ func (r *ResourceController) reconcileResource(resourceKind kube.Kind) reconcile
// create config-audit report
if !kube.IsRoleTypes(kube.Kind(kind)) || r.MergeRbacFindingWithConfigAudit {
reportBuilder := configauditreport.NewReportBuilder(r.Client.Scheme()).
ScopeResolver(&r.ObjectResolver.K8sScope).
Controller(resource).
ResourceSpecHash(resourceHash).
PluginConfigHash(policiesHash).
Expand All @@ -261,6 +234,7 @@ func (r *ResourceController) reconcileResource(resourceKind kube.Kind) reconcile
// create infra-assessment report
if k8sCoreComponent(resource) && r.Config.InfraAssessmentScannerEnabled {
infraReportBuilder := infraassessment.NewReportBuilder(r.Client.Scheme()).
ScopeResolver(&r.ObjectResolver.K8sScope).
Controller(resource).
ResourceSpecHash(resourceHash).
PluginConfigHash(policiesHash).
Expand All @@ -278,6 +252,7 @@ func (r *ResourceController) reconcileResource(resourceKind kube.Kind) reconcile
// create rbac-assessment report
if kube.IsRoleTypes(kube.Kind(kind)) && r.Config.RbacAssessmentScannerEnabled && !r.MergeRbacFindingWithConfigAudit {
rbacReportBuilder := rbacassessment.NewReportBuilder(r.Client.Scheme()).
ScopeResolver(&r.ObjectResolver.K8sScope).
Controller(resource).
ResourceSpecHash(resourceHash).
PluginConfigHash(policiesHash).
Expand Down Expand Up @@ -366,7 +341,7 @@ func (r *ResourceController) hasReport(ctx context.Context, owner kube.ObjectRef
if kube.IsRoleTypes(owner.Kind) {
io = r.RbacReadWriter
}
if kube.IsClusterScopedKind(string(owner.Kind)) {
if r.ObjectResolver.IsClusterScope(string(owner.Kind)) {
hasClusterReport, err := r.hasClusterReport(ctx, owner, podSpecHash, pluginConfigHash, io)
if err != nil {
return false, err
Expand Down
8 changes: 7 additions & 1 deletion pkg/infraassessment/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type ReportBuilder struct {
reportTTL *time.Duration
resourceLabelsToInclude []string
additionalReportLabels labels.Set
scopeResolver *kube.K8sScope
}

func NewReportBuilder(scheme *runtime.Scheme) *ReportBuilder {
Expand All @@ -43,6 +44,11 @@ func NewReportBuilder(scheme *runtime.Scheme) *ReportBuilder {
}
}

func (b *ReportBuilder) ScopeResolver(sr *kube.K8sScope) *ReportBuilder {
b.scopeResolver = sr
return b
}

func (b *ReportBuilder) Controller(controller client.Object) *ReportBuilder {
b.controller = controller
return b
Expand Down Expand Up @@ -175,7 +181,7 @@ func (b *ReportBuilder) GetClusterReport() (v1alpha1.ClusterInfraAssessmentRepor
}

func (b *ReportBuilder) Write(ctx context.Context, writer Writer) error {
if kube.IsClusterScopedKind(b.controller.GetObjectKind().GroupVersionKind().Kind) {
if b.scopeResolver.IsClusterScope(b.controller.GetObjectKind().GroupVersionKind().Kind) {
report, err := b.GetClusterReport()
if err != nil {
return err
Expand Down
Loading
Loading