Skip to content

Commit

Permalink
bugfix: rbac resource with capital letter name
Browse files Browse the repository at this point in the history
When rbac resources is having capital letter in its name then trivy-operator throws error for creating its configaudit report OR rbac report.
This happens bcoz capital letter name is not allowed in majority of the resources except rbac.
To resolve this, we will make sure that trivy-operator doesnot try create report with capital letter, if capital letter comes then we generate report with hashvalue name
- replace IsValidLabelValue to IsDNS1123Label which allows only lower case value other similar constraint on length

resolve: aquasecurity#343
  • Loading branch information
Devendrakumar Turkar authored and Devendrakumar Turkar committed Jun 23, 2023
1 parent ec6a40f commit 8a1d214
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 2 deletions.
2 changes: 1 addition & 1 deletion pkg/configauditreport/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (b *ReportBuilder) reportName() string {
kind := b.controller.GetObjectKind().GroupVersionKind().Kind
name := b.controller.GetName()
reportName := fmt.Sprintf("%s-%s", strings.ToLower(kind), name)
if len(validation.IsValidLabelValue(reportName)) == 0 {
if len(validation.IsDNS1123Label(reportName)) == 0 {
return reportName
}
return fmt.Sprintf("%s-%s", strings.ToLower(kind), kube.ComputeHash(name))
Expand Down
48 changes: 48 additions & 0 deletions pkg/configauditreport/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,52 @@ func TestReportBuilder(t *testing.T) {
Report: v1alpha1.ConfigAuditReportData{},
}))
})

t.Run("Should build report with lowercase name", func(t *testing.T) {
g := NewGomegaWithT(t)

report, err := configauditreport.NewReportBuilder(scheme.Scheme).
Controller(&rbacv1.Role{
TypeMeta: metav1.TypeMeta{
Kind: "Role",
APIVersion: "rbac.authorization.k8s.io/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "pod-Reader",
Labels: labels.Set{"tier": "tier-1", "owner": "team-a"},
Namespace: "test",
},
}).
ResourceSpecHash("xyz").
PluginConfigHash("nop").
Data(v1alpha1.ConfigAuditReportData{}).
ResourceLabelsToInclude([]string{"tier"}).
GetReport()

g.Expect(err).ToNot(HaveOccurred())
g.Expect(report).To(Equal(v1alpha1.ConfigAuditReport{
ObjectMeta: metav1.ObjectMeta{
Name: "role-65c67c5c64",
Namespace: "test",
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: "rbac.authorization.k8s.io/v1",
Kind: "Role",
Name: "pod-Reader",
Controller: pointer.Bool(true),
BlockOwnerDeletion: pointer.Bool(false),
},
},
Labels: map[string]string{
trivyoperator.LabelPluginConfigHash: "nop",
trivyoperator.LabelResourceKind: "Role",
trivyoperator.LabelResourceNamespace: "test",
trivyoperator.LabelResourceName: "pod-Reader",
"tier": "tier-1",
trivyoperator.LabelResourceSpecHash: "xyz",
},
},
Report: v1alpha1.ConfigAuditReportData{},
}))
})
}
6 changes: 6 additions & 0 deletions pkg/kube/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"hash"
"hash/fnv"
"regexp"

"github.com/aquasecurity/trivy-operator/pkg/trivyoperator"
"github.com/davecgh/go-spew/spew"
Expand Down Expand Up @@ -52,6 +53,11 @@ func GetContainerImagesFromJob(job *batchv1.Job) (ContainerImages, error) {
return containerImages, nil
}

func IsCapitalLetterExists(input string) bool {
var re = regexp.MustCompile(`[A-Z]`)
return re.FindString(input) != ""
}

// ComputeHash returns a hash value calculated from a given object.
// The hash will be safe encoded to avoid bad words.
func ComputeHash(obj interface{}) string {
Expand Down
19 changes: 19 additions & 0 deletions pkg/kube/resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,22 @@ func TestComputeHash(t *testing.T) {
})

}

func TestCapitalLetterExists(t *testing.T) {

tests := []struct {
name string
input string
want bool
}{
{name: "capital letter not exists", input: "pod-reader", want: false},
{name: "capital letter exists", input: "pod-Reader", want: true},
{name: "capital letter exists", input: "Pod-Reader", want: true},
{name: "capital letter not exists", input: "pod-reader-test", want: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, kube.IsCapitalLetterExists(tt.input), "IsCapitalLetterExists(%v)", tt.input)
})
}
}
2 changes: 1 addition & 1 deletion pkg/rbacassessment/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (b *ReportBuilder) reportName() string {
kind := b.controller.GetObjectKind().GroupVersionKind().Kind
name := b.controller.GetName()
reportName := fmt.Sprintf("%s-%s", strings.ToLower(kind), name)
if len(validation.IsValidLabelValue(reportName)) == 0 {
if len(validation.IsDNS1123Label(reportName)) == 0 {
return reportName
}
return fmt.Sprintf("%s-%s", strings.ToLower(kind), kube.ComputeHash(name))
Expand Down
49 changes: 49 additions & 0 deletions pkg/rbacassessment/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,55 @@ func TestReportBuilder(t *testing.T) {
g.Expect(report).To(Equal(assessmentReport))
})

t.Run("Should build report for namespaced resource with capital letter", func(t *testing.T) {
g := NewGomegaWithT(t)

report, err := rbacassessment.NewReportBuilder(scheme.Scheme).
Controller(&rbacv1.Role{
TypeMeta: metav1.TypeMeta{
Kind: "Role",
APIVersion: "rbac.authorization.k8s.io/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "some-Owner",
Namespace: "qa",
Labels: labels.Set{"tier": "tier-1", "owner": "team-a"},
},
Rules: []rbacv1.PolicyRule{},
}).
ResourceSpecHash("xyz").
PluginConfigHash("nop").
Data(v1alpha1.RbacAssessmentReportData{}).
ResourceLabelsToInclude([]string{"tier"}).
GetReport()
g.Expect(err).ToNot(HaveOccurred())
assessmentReport := v1alpha1.RbacAssessmentReport{
ObjectMeta: metav1.ObjectMeta{
Name: "role-5ccc5d4cff",
Namespace: "qa",
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: "rbac.authorization.k8s.io/v1",
Kind: "Role",
Name: "some-Owner",
Controller: pointer.Bool(true),
BlockOwnerDeletion: pointer.Bool(false),
},
},
Labels: map[string]string{
trivyoperator.LabelResourceKind: "Role",
trivyoperator.LabelResourceName: "some-Owner",
trivyoperator.LabelResourceNamespace: "qa",
trivyoperator.LabelResourceSpecHash: "xyz",
trivyoperator.LabelPluginConfigHash: "nop",
"tier": "tier-1",
},
},
Report: v1alpha1.RbacAssessmentReportData{},
}
g.Expect(report).To(Equal(assessmentReport))
})

t.Run("Should build report for cluster scoped resource", func(t *testing.T) {
g := NewGomegaWithT(t)

Expand Down

0 comments on commit 8a1d214

Please sign in to comment.