Skip to content

Commit

Permalink
chore: filter by resourceGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
cmendible committed Jul 31, 2024
1 parent c4aa85b commit d0130e4
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 114 deletions.
4 changes: 2 additions & 2 deletions internal/aprl_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func (sc AprlScanner) Scan(ctx context.Context, cred azcore.TokenCredential, ser
for i := 0; i < batches; i++ {
res := <-ch
for _, r := range res {
if filters.Azqr.Exclude.IsServiceExcluded(r.ResourceID) {
if filters.Azqr.IsServiceExcluded(r.ResourceID) {
continue
}
results = append(results, r)
Expand Down Expand Up @@ -258,7 +258,7 @@ func (sc AprlScanner) getGraphRules(service string, filters *azqr.Filters, aprl
r := map[string]azqr.AprlRecommendation{}
if i, ok := aprl[strings.ToLower(service)]; ok {
for _, recommendation := range i {
if filters.Azqr.Exclude.IsRecommendationExcluded(recommendation.RecommendationID) ||
if filters.Azqr.IsRecommendationExcluded(recommendation.RecommendationID) ||
strings.Contains(recommendation.GraphQuery, "cannot-be-validated-with-arg") ||
strings.Contains(recommendation.GraphQuery, "under-development") ||
strings.Contains(recommendation.GraphQuery, "under development") {
Expand Down
47 changes: 0 additions & 47 deletions internal/azqr/azqr.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,53 +249,6 @@ func ShouldSkipError(err error) bool {
return false
}

// func ListResourceGroups(ctx context.Context, cred azcore.TokenCredential, resourceGroup string, subscriptionID string, exclusions *filters.Filters, options *arm.ClientOptions) []string {
// resourceGroups := []string{}
// if resourceGroup != "" {
// exists, err := checkExistenceResourceGroup(ctx, subscriptionID, resourceGroup, cred, options)
// if err != nil {
// log.Fatal().Err(err).Msg("Failed to check existence of Resource Group")
// }

// if !exists {
// log.Fatal().Msgf("Resource Group %s does not exist", resourceGroup)
// }

// if exclusions.Azqr.Exclude.IsResourceGroupExcluded(fmt.Sprintf("/subscriptions/%s/resourceGroups/%s", subscriptionID, resourceGroup)) {
// log.Info().Msgf("Skipping subscriptions/...%s/resourceGroups/%s", subscriptionID[29:], resourceGroup)
// return resourceGroups
// }

// resourceGroups = append(resourceGroups, resourceGroup)
// } else {
// rgs, err := ListResourceGroup(ctx, cred, subscriptionID, options)
// if err != nil {
// log.Fatal().Err(err).Msg("Failed to list Resource Groups")
// }
// for _, rg := range rgs {
// if exclusions.Azqr.Exclude.IsResourceGroupExcluded(fmt.Sprintf("/subscriptions/%s/resourceGroups/%s", subscriptionID, *rg.Name)) {
// log.Info().Msgf("Skipping subscriptions/...%s/resourceGroups/%s", subscriptionID[29:], *rg.Name)
// continue
// }
// resourceGroups = append(resourceGroups, *rg.Name)
// }
// }
// return resourceGroups
// }

// func checkExistenceResourceGroup(ctx context.Context, subscriptionID string, resourceGroupName string, cred azcore.TokenCredential, options *arm.ClientOptions) (bool, error) {
// resourceGroupClient, err := armresources.NewResourceGroupsClient(subscriptionID, cred, options)
// if err != nil {
// return false, err
// }

// boolResp, err := resourceGroupClient.CheckExistence(ctx, resourceGroupName, nil)
// if err != nil {
// return false, err
// }
// return boolResp.Success, nil
// }

func ListResourceGroup(ctx context.Context, cred azcore.TokenCredential, subscriptionID string, options *arm.ClientOptions) ([]*armresources.ResourceGroup, error) {
resourceGroupClient, err := armresources.NewResourceGroupsClient(subscriptionID, cred, options)
if err != nil {
Expand Down
121 changes: 78 additions & 43 deletions internal/azqr/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,70 +16,81 @@ type (
}

AzqrFilter struct {
Exclude *Exclude `yaml:"exclude"`
Include *IncludeFilter `yaml:"include"`
Exclude *ExcludeFilter `yaml:"exclude"`
iSubscriptions map[string]bool
iResourceGroups map[string]bool
xSubscriptions map[string]bool
xResourceGroups map[string]bool
xServices map[string]bool
xRecommendations map[string]bool
}

// Exclude - Struct for Exclude
Exclude struct {
// ExcludeFilter - Struct for ExcludeFilter
ExcludeFilter struct {
Subscriptions []string `yaml:"subscriptions,flow"`
ResourceGroups []string `yaml:"resourceGroups,flow"`
Services []string `yaml:"services,flow"`
Recommendations []string `yaml:"recommendations,flow"`
subscriptions map[string]bool
resourceGroups map[string]bool
services map[string]bool
recommendations map[string]bool
}
)

func (e *Exclude) IsSubscriptionExcluded(subscriptionID string) bool {
if e.subscriptions == nil {
e.subscriptions = make(map[string]bool)
for _, id := range e.Subscriptions {
e.subscriptions[strings.ToLower(id)] = true
}
// IncludeFilter - Struct for IncludeFilter
IncludeFilter struct {
Subscriptions []string `yaml:"subscriptions,flow"`
ResourceGroups []string `yaml:"resourceGroups,flow"`
}
)

_, ok := e.subscriptions[strings.ToLower(subscriptionID)]

return ok
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 *Exclude) IsServiceExcluded(resourceID string) bool {
if e.services == nil {
e.services = make(map[string]bool)
for _, id := range e.Services {
e.services[strings.ToLower(id)] = true
}
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)
}

_, ok := e.services[strings.ToLower(resourceID)]

if !ok {
rgID := GetResourceGroupIDFromResourceID(resourceID)
ok = e.isResourceGroupExcluded(rgID)
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 *Exclude) IsRecommendationExcluded(recommendationID string) bool {
if e.recommendations == nil {
e.recommendations = make(map[string]bool)
for _, id := range e.Recommendations {
e.recommendations[strings.ToLower(id)] = true
}
func (e *AzqrFilter) IsServiceExcluded(resourceID string) bool {
rgID := GetResourceGroupIDFromResourceID(resourceID)
ok := e.isResourceGroupExcluded(rgID)

if !ok {
_, ok = e.xServices[strings.ToLower(resourceID)]
}

_, ok := e.recommendations[strings.ToLower(recommendationID)]
return ok
}

func (e *AzqrFilter) IsRecommendationExcluded(recommendationID string) bool {
_, ok := e.xRecommendations[strings.ToLower(recommendationID)]
return ok
}

func LoadFilters(filterFile string) *Filters {
filters := &Filters{
Azqr: &AzqrFilter{
Exclude: &Exclude{
Include: &IncludeFilter{
Subscriptions: []string{},
ResourceGroups: []string{},
},
Exclude: &ExcludeFilter{
Subscriptions: []string{},
ResourceGroups: []string{},
Services: []string{},
Expand All @@ -99,18 +110,42 @@ func LoadFilters(filterFile string) *Filters {
}
}

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
}

return filters
}

func (e *Exclude) isResourceGroupExcluded(resourceGroupID string) bool {
if e.resourceGroups == nil {
e.resourceGroups = make(map[string]bool)
for _, id := range e.ResourceGroups {
e.resourceGroups[strings.ToLower(id)] = true
}
func (e *AzqrFilter) isResourceGroupExcluded(resourceGroupID string) bool {
// Check if the resource group is included
_, ok := e.iResourceGroups[strings.ToLower(resourceGroupID)]
if ok {
return false
}

_, ok := e.resourceGroups[strings.ToLower(resourceGroupID)]
// 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
}
22 changes: 15 additions & 7 deletions internal/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,24 @@ func (sc Scanner) Scan(params *ScanParams) {
log.Debug().Msg("Debug logging enabled")
}

// generate output file name
outputFile := sc.generateOutputFileName(params.OutputName)

// load filters
filters := azqr.LoadFilters(params.FilterFile)

// validate input
if params.SubscriptionID == "" && params.ResourceGroup != "" {
log.Fatal().Msg("Resource Group name can only be used with a Subscription Id")
}

// generate output file name
outputFile := sc.generateOutputFileName(params.OutputName)
if params.SubscriptionID != "" {
filters.Azqr.AddSubscription(params.SubscriptionID)
}

// load filters
filters := azqr.LoadFilters(params.FilterFile)
if params.ResourceGroup != "" {
filters.Azqr.AddResourceGroup(fmt.Sprintf("/subscriptions/%s/resourceGroups/%s", params.SubscriptionID, params.ResourceGroup))
}

// create Azure credentials
cred := sc.newAzureCredential(params.ForceAzureCliCredential)
Expand Down Expand Up @@ -104,13 +112,13 @@ func (sc Scanner) Scan(params *ScanParams) {
reportData.Recomendations, reportData.AprlData = aprlScanner.Scan(ctx, cred, params.ServiceScanners, filters, subscriptions)

resourceScanner := scanners.ResourceScanner{}
reportData.Resources = resourceScanner.GetAllResources(ctx, cred, subscriptions)
reportData.Resources = resourceScanner.GetAllResources(ctx, cred, subscriptions, filters)

// For each service scanner, get the recommendations list
if params.UseAzqrRecommendations {
for _, s := range params.ServiceScanners {
for i, r := range s.GetRecommendations() {
if filters.Azqr.Exclude.IsRecommendationExcluded(r.RecommendationID) {
if filters.Azqr.IsRecommendationExcluded(r.RecommendationID) {
continue
}

Expand Down Expand Up @@ -187,7 +195,7 @@ func (sc Scanner) Scan(params *ScanParams) {
res := <-ch
for _, r := range res {
// check if the resource is excluded
if filters.Azqr.Exclude.IsServiceExcluded(r.ResourceID()) {
if filters.Azqr.IsServiceExcluded(r.ResourceID()) {
continue
}
reportData.AzqrData = append(reportData.AzqrData, r)
Expand Down
33 changes: 19 additions & 14 deletions internal/scanners/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

type ResourceScanner struct{}

func (sc ResourceScanner) GetAllResources(ctx context.Context, cred azcore.TokenCredential, subscriptions map[string]string) []*azqr.Resource {
func (sc ResourceScanner) GetAllResources(ctx context.Context, cred azcore.TokenCredential, subscriptions map[string]string, filters *azqr.Filters) []*azqr.Resource {
azqr.LogResourceTypeScan("All Resources")

graphClient := graph.NewGraphQuery(cred)
Expand All @@ -23,11 +23,15 @@ func (sc ResourceScanner) GetAllResources(ctx context.Context, cred azcore.Token
subs = append(subs, &s)
}
result := graphClient.Query(ctx, query, subs)
resources := make([]*azqr.Resource, len(result.Data))
resources := []*azqr.Resource{}
if result.Data != nil {
for i, row := range result.Data {
for _, row := range result.Data {
m := row.(map[string]interface{})

if filters.Azqr.IsServiceExcluded(m["id"].(string)) {
continue
}

skuName := ""
if m["sku_name"] != nil {
skuName = m["sku_name"].(string)
Expand All @@ -53,17 +57,18 @@ func (sc ResourceScanner) GetAllResources(ctx context.Context, cred azcore.Token
location = m["location"].(string)
}

resources[i] = &azqr.Resource{
ID: m["id"].(string),
SubscriptionID: m["subscriptionId"].(string),
ResourceGroup: resourceGroup,
Location: location,
Type: m["type"].(string),
Name: m["name"].(string),
SkuName: skuName,
SkuTier: skuTier,
Kind: kind,
}
resources = append(
resources,
&azqr.Resource{
ID: m["id"].(string),
SubscriptionID: m["subscriptionId"].(string),
ResourceGroup: resourceGroup,
Location: location,
Type: m["type"].(string),
Name: m["name"].(string),
SkuName: skuName,
SkuTier: skuTier,
Kind: kind})
}
}
return resources
Expand Down
2 changes: 1 addition & 1 deletion internal/scanners/subscriptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (sc SubcriptionScanner) ListSubscriptions(ctx context.Context, cred azcore.
// if subscriptionID is empty, return filtered subscriptions. Otherwise, return only the specified subscription
sid := *s.SubscriptionID
if subscriptionID == "" || subscriptionID == sid {
if filters.Azqr.Exclude.IsSubscriptionExcluded(sid) {
if filters.Azqr.IsSubscriptionExcluded(sid) {
log.Info().Msgf("Skipping subscriptions/...%s", sid[29:])
continue
}
Expand Down

0 comments on commit d0130e4

Please sign in to comment.