Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ erc | Microsoft.Network/expressRouteCircuits
erc | Microsoft.Network/ExpressRoutePorts
evgd | Microsoft.EventGrid/domains
evh | Microsoft.EventHub/namespaces
fabric | Microsoft.Fabric/capacities
fdfp | Microsoft.Network/frontdoorWebApplicationFirewallPolicies
gal | Microsoft.Compute/galleries
hpc | Specialized.Workload/HPC
Expand Down
22 changes: 22 additions & 0 deletions cmd/azqr/commands/fabric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package commands

import (
"github.com/spf13/cobra"
)

func init() {
scanCmd.AddCommand(fabricCmd)
}

var fabricCmd = &cobra.Command{
Use: "fabric",
Short: "Scan Microsoft Fabric Capacities",
Long: "Scan Microsoft Fabric Capacities",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
scan(cmd, []string{"fabric"})
},
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/datafactory/armdatafactory v1.3.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventgrid/armeventgrid v1.0.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.3.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/fabric/armfabric v1.0.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.5.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/kusto/armkusto v1.3.1
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/logic/armlogic v1.2.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventgrid/armeventgrid v1.
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventgrid/armeventgrid v1.0.0/go.mod h1:t8kRpcgm+RdImuJgHG6SfoQ0tpb9LGl7MF1E6u0yeeA=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.3.0 h1:4hGvxD72TluuFIXVr8f4XkKZfqAa7Pj61t0jmQ7+kes=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.3.0/go.mod h1:TSH7DcFItwAufy0Lz+Ft2cyopExCpxbOxI5SkH4dRNo=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/fabric/armfabric v1.0.0 h1:rSss+KFqv/y2WeWCVjNmfPL1riYJ8dTbE0HqidCowuk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/fabric/armfabric v1.0.0/go.mod h1:oiQJZy3KaFouyQYLQow7+Zek9MS885GJ3u8YCmuS9wQ=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
Expand Down
1 change: 1 addition & 0 deletions internal/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import (
_ "github.com/Azure/azqr/internal/scanners/erc"
_ "github.com/Azure/azqr/internal/scanners/evgd"
_ "github.com/Azure/azqr/internal/scanners/evh"
_ "github.com/Azure/azqr/internal/scanners/fabric"
_ "github.com/Azure/azqr/internal/scanners/fdfp"
_ "github.com/Azure/azqr/internal/scanners/gal"
_ "github.com/Azure/azqr/internal/scanners/hpc"
Expand Down
76 changes: 76 additions & 0 deletions internal/scanners/fabric/fabric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package fabric

import (
"github.com/Azure/azqr/internal/models"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/fabric/armfabric"
)

func init() {
models.ScannerList["fabric"] = []models.IAzureScanner{&FabricScanner{}}
}

// FabricScanner - Scanner for Microsoft Fabric Capacities
type FabricScanner struct {
config *models.ScannerConfig
client *armfabric.CapacitiesClient
}

// Init - Initializes the FabricScanner
func (c *FabricScanner) Init(config *models.ScannerConfig) error {
c.config = config
var err error
c.client, err = armfabric.NewCapacitiesClient(config.SubscriptionID, config.Cred, config.ClientOptions)
return err
}

// Scan - Scans all Microsoft Fabric Capacities in a Subscription
func (c *FabricScanner) Scan(scanContext *models.ScanContext) ([]*models.AzqrServiceResult, error) {
models.LogSubscriptionScan(c.config.SubscriptionID, c.ResourceTypes()[0])

capacities, err := c.listCapacities()
if err != nil {
if models.ShouldSkipError(err) {
return nil, nil
}
return nil, err
}
engine := models.RecommendationEngine{}
rules := c.GetRecommendations()
results := []*models.AzqrServiceResult{}

for _, capacity := range capacities {
rr := engine.EvaluateRecommendations(rules, capacity, scanContext)

results = append(results, &models.AzqrServiceResult{
SubscriptionID: c.config.SubscriptionID,
SubscriptionName: c.config.SubscriptionName,
ResourceGroup: models.GetResourceGroupFromResourceID(*capacity.ID),
ServiceName: *capacity.Name,
Type: *capacity.Type,
Location: *capacity.Location,
Recommendations: rr,
})
}
return results, nil
}

func (c *FabricScanner) listCapacities() ([]*armfabric.Capacity, error) {
pager := c.client.NewListBySubscriptionPager(nil)

capacities := make([]*armfabric.Capacity, 0)
for pager.More() {
resp, err := pager.NextPage(c.config.Ctx)
if err != nil {
return nil, err
}
capacities = append(capacities, resp.Value...)
}
return capacities, nil
}

func (a *FabricScanner) ResourceTypes() []string {
return []string{"Microsoft.Fabric/capacities"}
}
100 changes: 100 additions & 0 deletions internal/scanners/fabric/rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package fabric

import (
"strings"

"github.com/Azure/azqr/internal/models"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/fabric/armfabric"
)

// GetRecommendations - Returns the rules for the FabricScanner
func (a *FabricScanner) GetRecommendations() map[string]models.AzqrRecommendation {
return map[string]models.AzqrRecommendation{
"fabric-001": {
RecommendationID: "fabric-001",
ResourceType: "Microsoft.Fabric/capacities",
Category: models.CategoryMonitoringAndAlerting,
Recommendation: "Fabric Capacity should have diagnostic settings enabled",
Impact: models.ImpactLow,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
service := target.(*armfabric.Capacity)
_, ok := scanContext.DiagnosticsSettings[strings.ToLower(*service.ID)]
return !ok, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/fabric/admin/monitoring-overview",
},
"fabric-002": {
RecommendationID: "fabric-002",
ResourceType: "Microsoft.Fabric/capacities",
Category: models.CategoryHighAvailability,
Recommendation: "Fabric Capacity should have a SLA",
RecommendationType: models.TypeSLA,
Impact: models.ImpactHigh,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
return false, "99.9%"
},
LearnMoreUrl: "https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services",
},
"fabric-003": {
RecommendationID: "fabric-003",
ResourceType: "Microsoft.Fabric/capacities",
Category: models.CategoryGovernance,
Recommendation: "Fabric Capacity Name should comply with naming conventions",
Impact: models.ImpactLow,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armfabric.Capacity)
caf := strings.HasPrefix(*c.Name, "fc")
return !caf, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations",
},
"fabric-004": {
RecommendationID: "fabric-004",
ResourceType: "Microsoft.Fabric/capacities",
Category: models.CategoryGovernance,
Recommendation: "Fabric Capacity should have tags defined",
Impact: models.ImpactLow,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armfabric.Capacity)
return len(c.Tags) == 0, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources",
},
"fabric-005": {
RecommendationID: "fabric-005",
ResourceType: "Microsoft.Fabric/capacities",
Category: models.CategoryOtherBestPractices,
Recommendation: "Fabric Capacity should be in Active state",
Impact: models.ImpactMedium,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armfabric.Capacity)
state := ""
if c.Properties != nil && c.Properties.State != nil {
state = string(*c.Properties.State)
}
isActive := strings.EqualFold(state, "Active")
return !isActive, state
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/fabric/enterprise/pause-resume",
},
"fabric-006": {
RecommendationID: "fabric-006",
ResourceType: "Microsoft.Fabric/capacities",
Category: models.CategorySecurity,
Recommendation: "Fabric Capacity should have administrators configured",
Impact: models.ImpactMedium,
Eval: func(target interface{}, scanContext *models.ScanContext) (bool, string) {
c := target.(*armfabric.Capacity)
hasAdmins := c.Properties != nil &&
c.Properties.Administration != nil &&
c.Properties.Administration.Members != nil &&
len(c.Properties.Administration.Members) > 0
return !hasAdmins, ""
},
LearnMoreUrl: "https://learn.microsoft.com/en-us/fabric/admin/capacity-settings",
},
}
}
Loading