@@ -27,17 +27,20 @@ type queryBuilder struct {
2727 collection * storage.ResourceCollection
2828 collectionQueryResolver collectionDataStore.QueryResolver
2929 dataStartTime time.Time
30+ entityScope * storage.EntityScope
3031}
3132
3233// NewVulnReportQueryBuilder builds a query builder to build scope and cve filtering queries for vuln reporting
33- func NewVulnReportQueryBuilder (collection * storage.ResourceCollection , vulnFilters * storage.VulnerabilityReportFilters ,
34+ func NewVulnReportQueryBuilder (collection * storage.ResourceCollection , entityScope * storage. EntityScope , vulnFilters * storage.VulnerabilityReportFilters ,
3435 collectionQueryRes collectionDataStore.QueryResolver , dataStartTime time.Time ) * queryBuilder {
3536 return & queryBuilder {
36- vulnFilters : vulnFilters ,
3737 collection : collection ,
38+ entityScope : entityScope ,
39+ vulnFilters : vulnFilters ,
3840 collectionQueryResolver : collectionQueryRes ,
3941 dataStartTime : dataStartTime ,
4042 }
43+
4144}
4245
4346// BuildQuery builds scope and cve filtering queries for vuln reporting
@@ -46,7 +49,17 @@ func (q *queryBuilder) BuildQuery(
4649 clusters []effectiveaccessscope.Cluster ,
4750 namespaces []effectiveaccessscope.Namespace ,
4851) (* ReportQuery , error ) {
49- deploymentsQuery , err := q .collectionQueryResolver .ResolveCollectionQuery (ctx , q .collection )
52+ deploymentsQuery := search .MatchNoneQuery ()
53+ var err error
54+ if q .collection != nil {
55+ deploymentsQuery , err = q .collectionQueryResolver .ResolveCollectionQuery (ctx , q .collection )
56+ } else if q .entityScope != nil {
57+ entityScopeQueryString , err := q .buildEntityScopeQueryString ()
58+ if err != nil {
59+ return nil , err
60+ }
61+ deploymentsQuery , err = search .ParseQuery (entityScopeQueryString , search .MatchAllIfEmpty ())
62+ }
5063 if err != nil {
5164 return nil , err
5265 }
@@ -66,7 +79,112 @@ func (q *queryBuilder) BuildQuery(
6679 }, nil
6780}
6881
82+ func (q * queryBuilder ) buildEntityScopeQueryString () (string , error ) {
83+ rules := q .entityScope .GetRules ()
84+ if len (rules ) == 0 {
85+ return "" , nil
86+ }
87+
88+ var conjuncts []string
89+ for _ , rule := range rules {
90+ fieldLabel , err := entityScopeRuleToFieldLabel (rule )
91+ if err != nil {
92+ return "" , err
93+ }
94+ isLabel := fieldLabel == search .DeploymentLabel ||
95+ fieldLabel == search .NamespaceLabel ||
96+ fieldLabel == search .ClusterLabel
97+
98+ values := make ([]string , 0 , len (rule .GetValues ()))
99+ for _ , rv := range rule .GetValues () {
100+ val := rv .GetValue ()
101+ if rv .GetMatchType () == storage .MatchType_REGEX {
102+ val = search .RegexPrefix + val
103+ }
104+ values = append (values , val )
105+ }
106+
107+ if len (values ) == 0 {
108+ continue
109+ }
110+
111+ var qb * search.QueryBuilder
112+ if isLabel {
113+ for _ , v := range values {
114+ key , value := splitLabelValue (v )
115+ qb = search .NewQueryBuilder ().AddMapQuery (fieldLabel , key , value )
116+ conjuncts = append (conjuncts , qb .Query ())
117+ }
118+ } else if rule .GetValues ()[0 ].GetMatchType () == storage .MatchType_REGEX {
119+ qb = search .NewQueryBuilder ().AddStrings (fieldLabel , values ... )
120+ conjuncts = append (conjuncts , qb .Query ())
121+ } else {
122+ qb = search .NewQueryBuilder ().AddExactMatches (fieldLabel , values ... )
123+ conjuncts = append (conjuncts , qb .Query ())
124+ }
125+ }
126+
127+ return strings .Join (conjuncts , "+" ), nil
128+ }
129+
130+ func entityScopeRuleToFieldLabel (rule * storage.EntityScopeRule ) (search.FieldLabel , error ) {
131+ switch rule .GetEntity () {
132+ case storage .EntityType_ENTITY_TYPE_DEPLOYMENT :
133+ switch rule .GetField () {
134+ case storage .EntityField_FIELD_NAME :
135+ return search .DeploymentName , nil
136+ case storage .EntityField_FIELD_LABEL :
137+ return search .DeploymentLabel , nil
138+ case storage .EntityField_FIELD_ANNOTATION :
139+ return search .DeploymentAnnotation , nil
140+ }
141+ case storage .EntityType_ENTITY_TYPE_NAMESPACE :
142+ switch rule .GetField () {
143+ case storage .EntityField_FIELD_NAME :
144+ return search .Namespace , nil
145+ case storage .EntityField_FIELD_LABEL :
146+ return search .NamespaceLabel , nil
147+ case storage .EntityField_FIELD_ANNOTATION :
148+ return search .NamespaceAnnotation , nil
149+ }
150+ case storage .EntityType_ENTITY_TYPE_CLUSTER :
151+ switch rule .GetField () {
152+ case storage .EntityField_FIELD_NAME :
153+ return search .Cluster , nil
154+ case storage .EntityField_FIELD_LABEL :
155+ return search .ClusterLabel , nil
156+ }
157+ }
158+ return "" , fmt .Errorf ("unsupported entity/field combination: %s/%s" , rule .GetEntity (), rule .GetField ())
159+ }
160+
161+ func splitLabelValue (labelVal string ) (string , string ) {
162+ parts := strings .SplitN (labelVal , "=" , 2 )
163+ if len (parts ) == 2 {
164+ return fmt .Sprintf ("%q" , parts [0 ]), fmt .Sprintf ("%q" , parts [1 ])
165+ }
166+ return fmt .Sprintf ("%q" , labelVal ), fmt .Sprintf ("%q" , "" )
167+ }
168+
69169func (q * queryBuilder ) buildCVEAttributesQuery () (string , error ) {
170+
171+ vulnReportFilters := q .vulnFilters
172+ var conjuncts []string
173+ if q .collection != nil {
174+ conjuncts = q .addSeverityFixabilityFiltersCollectionScopedReports ()
175+ } else if q .entityScope != nil {
176+ conjuncts = append (conjuncts , q .vulnFilters .GetQuery ())
177+ }
178+ if filterVulnsByFirstOccurrenceTime (vulnReportFilters ) {
179+ startTimeStr := fmt .Sprintf (">=%s" , q .dataStartTime .Format ("01/02/2006 3:04:05 PM MST" ))
180+ tsQ := search .NewQueryBuilder ().AddStrings (search .FirstImageOccurrenceTimestamp , startTimeStr ).Query ()
181+ conjuncts = append (conjuncts , tsQ )
182+ }
183+ return strings .Join (conjuncts , "+" ), nil
184+ }
185+
186+ func (q * queryBuilder ) addSeverityFixabilityFiltersCollectionScopedReports () []string {
187+
70188 vulnReportFilters := q .vulnFilters
71189 var conjuncts []string
72190
@@ -86,14 +204,7 @@ func (q *queryBuilder) buildCVEAttributesQuery() (string, error) {
86204 if len (severities ) > 0 {
87205 conjuncts = append (conjuncts , search .NewQueryBuilder ().AddExactMatches (search .Severity , severities ... ).Query ())
88206 }
89-
90- if filterVulnsByFirstOccurrenceTime (vulnReportFilters ) {
91- startTimeStr := fmt .Sprintf (">=%s" , q .dataStartTime .Format ("01/02/2006 3:04:05 PM MST" ))
92- tsQ := search .NewQueryBuilder ().AddStrings (search .FirstImageOccurrenceTimestamp , startTimeStr ).Query ()
93- conjuncts = append (conjuncts , tsQ )
94- }
95-
96- return strings .Join (conjuncts , "+" ), nil
207+ return conjuncts
97208}
98209
99210func (q * queryBuilder ) buildAccessScopeQuery (
0 commit comments