internal/models/filters.go (165 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. package models import ( "os" "strings" "github.com/rs/zerolog/log" "gopkg.in/yaml.v3" ) type ( Filters struct { Azqr *AzqrFilter `yaml:"azqr" json:"azqr"` } AzqrFilter struct { Include *IncludeFilter `yaml:"include" json:"include"` Exclude *ExcludeFilter `yaml:"exclude" json:"exclude"` iSubscriptions map[string]bool iResourceGroups map[string]bool iResourceTypes map[string]bool xSubscriptions map[string]bool xResourceGroups map[string]bool xServices map[string]bool xRecommendations map[string]bool Scanners []IAzureScanner } // ExcludeFilter - Struct for ExcludeFilter ExcludeFilter struct { Subscriptions []string `yaml:"subscriptions,flow" json:"subscriptions"` ResourceGroups []string `yaml:"resourceGroups,flow" json:"resourceGroups"` Services []string `yaml:"services,flow" json:"services"` Recommendations []string `yaml:"recommendations,flow" json:"recommendations"` } // IncludeFilter - Struct for IncludeFilter IncludeFilter struct { Subscriptions []string `yaml:"subscriptions,flow" json:"subscriptions"` ResourceGroups []string `yaml:"resourceGroups,flow" json:"resourceGroups"` ResourceTypes []string `yaml:"resourceTypes,flow"` } ) func (e *AzqrFilter) AddSubscription(subscriptionID string) { if e.iSubscriptions == nil { e.iSubscriptions = make(map[string]bool) } e.iSubscriptions[strings.ToLower(subscriptionID)] = true e.Include.Subscriptions = append(e.Include.Subscriptions, subscriptionID) } func (e *AzqrFilter) AddResourceGroup(resourceGroupID string) { if e.iResourceGroups == nil { e.iResourceGroups = make(map[string]bool) } e.iResourceGroups[strings.ToLower(resourceGroupID)] = true e.Include.ResourceGroups = append(e.Include.ResourceGroups, resourceGroupID) } func (e *AzqrFilter) IsSubscriptionExcluded(subscriptionID string) bool { _, ok := e.iSubscriptions[strings.ToLower(subscriptionID)] if ok { return false } _, ok = e.xSubscriptions[strings.ToLower(subscriptionID)] return ok } func (e *AzqrFilter) IsServiceExcluded(resourceID string) bool { t := GetResourceTypeFromResourceID(resourceID) if _, included := e.iResourceTypes[strings.ToLower(t)]; included { sID := GetSubscriptionFromResourceID(resourceID) excluded := e.IsSubscriptionExcluded(sID) if !excluded { rgID := GetResourceGroupIDFromResourceID(resourceID) excluded = e.isResourceGroupExcluded(rgID) if !excluded { _, excluded = e.xServices[strings.ToLower(resourceID)] } } if excluded { log.Debug().Msgf("Service is excluded: %s", resourceID) } return excluded } else { log.Debug().Msgf("Service type is excluded: %s", t) return true } } func (e *AzqrFilter) IsRecommendationExcluded(recommendationID string) bool { _, ok := e.xRecommendations[strings.ToLower(recommendationID)] return ok } func (e *AzqrFilter) IsResourceTypeExcluded(resourceType string) bool { _, ok := e.iResourceTypes[strings.ToLower(resourceType)] return !ok } func NewFilters() *Filters { filters := &Filters{ Azqr: &AzqrFilter{ Include: &IncludeFilter{ Subscriptions: []string{}, ResourceGroups: []string{}, ResourceTypes: []string{}, }, Exclude: &ExcludeFilter{ Subscriptions: []string{}, ResourceGroups: []string{}, Services: []string{}, Recommendations: []string{}, }, Scanners: []IAzureScanner{}, }, } return filters } func LoadFilters(filterFile string, scannerKeys []string) *Filters { filters := NewFilters() if filterFile != "" { data, err := os.ReadFile(filterFile) if err != nil { log.Fatal().Err(err).Msgf("failed reading data from file: %s", filterFile) } err = yaml.Unmarshal([]byte(data), &filters) if err != nil { log.Fatal().Err(err).Msgf("failed parsing yaml from file: %s", filterFile) } } filters.Azqr.xResourceGroups = make(map[string]bool) for _, id := range filters.Azqr.Exclude.ResourceGroups { filters.Azqr.xResourceGroups[strings.ToLower(id)] = true } filters.Azqr.xSubscriptions = make(map[string]bool) for _, id := range filters.Azqr.Exclude.Subscriptions { filters.Azqr.xSubscriptions[strings.ToLower(id)] = true } filters.Azqr.xServices = make(map[string]bool) for _, id := range filters.Azqr.Exclude.Services { filters.Azqr.xServices[strings.ToLower(id)] = true } filters.Azqr.xRecommendations = make(map[string]bool) for _, id := range filters.Azqr.Exclude.Recommendations { filters.Azqr.xRecommendations[strings.ToLower(id)] = true } s := []IAzureScanner{} if len(scannerKeys) > 1 && len(filters.Azqr.Include.ResourceTypes) > 0 { for _, key := range filters.Azqr.Include.ResourceTypes { if scannerList, exists := ScannerList[key]; exists { s = append(s, scannerList...) } } } else if len(scannerKeys) == 1 { s = append(s, ScannerList[scannerKeys[0]]...) } else { _, s = GetScanners() } filters.Azqr.Scanners = s filters.Azqr.iResourceTypes = make(map[string]bool) for _, t := range s { for _, r := range t.ResourceTypes() { filters.Azqr.iResourceTypes[strings.ToLower(r)] = true } } return filters } func (e *AzqrFilter) isResourceGroupExcluded(resourceGroupID string) bool { // Check if the resource group is included _, ok := e.iResourceGroups[strings.ToLower(resourceGroupID)] if ok { return false } // If not included, but there are included resource groups, then exclude it if len(e.iResourceGroups) > 0 { return true } // Check if the resource group is excluded _, ok = e.xResourceGroups[strings.ToLower(resourceGroupID)] return ok }