Skip to content

Commit

Permalink
Added Databricks scanner. #146
Browse files Browse the repository at this point in the history
  • Loading branch information
cmendible committed Oct 16, 2023
1 parent 2bad783 commit 5d9f2fb
Show file tree
Hide file tree
Showing 11 changed files with 600 additions and 248 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ To learn more about the rules used by **Azure Quick Review (azqr)** for generati
* Azure Container Instances
* Azure Container Registry
* Azure Cosmos DB
* Azure Databricks
* Azure Data Explorer
* Azure Data Factory
* Azure Database for MariaDB
Expand Down
28 changes: 28 additions & 0 deletions cmd/azqr/dbw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package azqr

import (
"github.com/Azure/azqr/internal/scanners"
"github.com/Azure/azqr/internal/scanners/dbw"
"github.com/spf13/cobra"
)

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

var dbwCmd = &cobra.Command{
Use: "dbw",
Short: "Scan Azure Databricks",
Long: "Scan Azure Databricks",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
serviceScanners := []scanners.IAzureScanner{
&dbw.DatabricksScanner{},
}

scan(cmd, serviceScanners)
},
}
2 changes: 2 additions & 0 deletions cmd/azqr/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/Azure/azqr/internal/scanners/cog"
"github.com/Azure/azqr/internal/scanners/cosmos"
"github.com/Azure/azqr/internal/scanners/cr"
"github.com/Azure/azqr/internal/scanners/dbw"
"github.com/Azure/azqr/internal/scanners/dec"
"github.com/Azure/azqr/internal/scanners/evgd"
"github.com/Azure/azqr/internal/scanners/evh"
Expand Down Expand Up @@ -52,6 +53,7 @@ var rulesCmd = &cobra.Command{
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
serviceScanners := []scanners.IAzureScanner{
&dbw.DatabricksScanner{},
&adf.DataFactoryScanner{},
&afd.FrontDoorScanner{},
&afw.FirewallScanner{},
Expand Down
2 changes: 2 additions & 0 deletions cmd/azqr/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/Azure/azqr/internal/scanners/cog"
"github.com/Azure/azqr/internal/scanners/cosmos"
"github.com/Azure/azqr/internal/scanners/cr"
"github.com/Azure/azqr/internal/scanners/dbw"
"github.com/Azure/azqr/internal/scanners/dec"
"github.com/Azure/azqr/internal/scanners/evgd"
"github.com/Azure/azqr/internal/scanners/evh"
Expand Down Expand Up @@ -75,6 +76,7 @@ var scanCmd = &cobra.Command{
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
serviceScanners := []scanners.IAzureScanner{
&dbw.DatabricksScanner{},
&adf.DataFactoryScanner{},
&afd.FrontDoorScanner{},
&afw.FirewallScanner{},
Expand Down
1 change: 1 addition & 0 deletions docs/content/en/docs/Overview/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ To learn more about the rules used by **Azure Quick Review (azqr)** for generati
* Azure Container Instances
* Azure Container Registry
* Azure Cosmos DB
* Azure Databricks
* Azure Data Explorer
* Azure Data Factory
* Azure Database for MariaDB
Expand Down
496 changes: 251 additions & 245 deletions docs/content/en/docs/Rules/_index.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/Azure/azqr
go 1.19

require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0-beta.1
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0-beta.1
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/advisor/armadvisor v1.0.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/apimanagement/armapimanagement v1.0.0
Expand All @@ -19,6 +19,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice v1.0.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos v1.0.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/costmanagement/armcostmanagement v1.1.1
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/databricks/armdatabricks v0.7.1
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.0.0
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0-beta.1 h1:TpBJ3UP3Vx9OBk1nP/5FynUmQXPeIq2RXadb4gq8ZgU=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0-beta.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0-beta.1 h1:U7R494cK8Co9Hre1WvugptflSxb6mJ8pVvvU1mFGFmg=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0-beta.1/go.mod h1:OcBSIbRqQILk3z7FoYL+RcoXl4jHPm4FL14OU9jAB8g=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
Expand Down Expand Up @@ -32,6 +32,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos v1.0.0 h1
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos v1.0.0/go.mod h1:Qpe/qN9d5IQ7WPtTXMRCd6+BWTnhi3sxXVys6oJ5Vho=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/costmanagement/armcostmanagement v1.1.1 h1:ehSLdbLah6kk6HTVc6e/lrbmbz7MMbpNxkOd3OYlhB0=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/costmanagement/armcostmanagement v1.1.1/go.mod h1:Am1cUioOk0HdZIsjpXJkQ4RIeQbwYsW6LkNIc5z/5XY=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/databricks/armdatabricks v0.7.1 h1:90KaNwKY4bDNuFcF6nL2PON5iI2y8J1QgAd0LBrl1S4=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/databricks/armdatabricks v0.7.1/go.mod h1:OrZZhwsGHh57EI7FJ3hZGH3TV4kCWnEIM/AlCv2QPg0=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/datafactory/armdatafactory v1.3.0 h1:pmKRJksZidUYbOMQ2wtVm4L9q0BadVfBsF/fPKUUnjg=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/datafactory/armdatafactory v1.3.0/go.mod h1:CmZkcUHLqzY7I+io4fQda7G1ZJ/4R0b3/iPFzEWWl7E=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventgrid/armeventgrid v1.0.0 h1:w6b0+FygDpqM7g5cjbeyPoBzgxVHwwt2vCUvTz1oFY8=
Expand Down
66 changes: 66 additions & 0 deletions internal/scanners/dbw/dbw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package dbw

import (
"github.com/rs/zerolog/log"

"github.com/Azure/azqr/internal/scanners"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/databricks/armdatabricks"
)

// DatabricksScanner - Scanner for Azure Databricks
type DatabricksScanner struct {
config *scanners.ScannerConfig
client *armdatabricks.WorkspacesClient
}

// Init - Initializes the DatabricksScanner
func (c *DatabricksScanner) Init(config *scanners.ScannerConfig) error {
c.config = config
var err error
c.client, err = armdatabricks.NewWorkspacesClient(config.SubscriptionID, config.Cred, config.ClientOptions)
return err
}

// Scan - Scans all Azure Databricks in a Resource Group
func (c *DatabricksScanner) Scan(resourceGroupName string, scanContext *scanners.ScanContext) ([]scanners.AzureServiceResult, error) {
log.Info().Stack().Msgf("Scanning Azure Databricks in Resource Group %s", resourceGroupName)

workspaces, err := c.listWorkspaces(resourceGroupName)
if err != nil {
return nil, err
}
engine := scanners.RuleEngine{}
rules := c.GetRules()
results := []scanners.AzureServiceResult{}

for _, ws := range workspaces {
rr := engine.EvaluateRules(rules, ws, scanContext)

results = append(results, scanners.AzureServiceResult{
SubscriptionID: c.config.SubscriptionID,
ResourceGroup: resourceGroupName,
ServiceName: *ws.Name,
Type: *ws.Type,
Location: *ws.Location,
Rules: rr,
})
}
return results, nil
}

func (c *DatabricksScanner) listWorkspaces(resourceGroupName string) ([]*armdatabricks.Workspace, error) {
pager := c.client.NewListByResourceGroupPager(resourceGroupName, nil)

registries := make([]*armdatabricks.Workspace, 0)
for pager.More() {
resp, err := pager.NextPage(c.config.Ctx)
if err != nil {
return nil, err
}
registries = append(registries, resp.Value...)
}
return registries, nil
}
98 changes: 98 additions & 0 deletions internal/scanners/dbw/rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package dbw

import (
"strings"

"github.com/Azure/azqr/internal/ref"
"github.com/Azure/azqr/internal/scanners"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/databricks/armdatabricks"
)

// GetRules - Returns the rules for the DatabricksScanner
func (a *DatabricksScanner) GetRules() map[string]scanners.AzureRule {
return map[string]scanners.AzureRule{
"dbw-001": {
Id: "dbw-001",
Category: scanners.RulesCategoryReliability,
Subcategory: scanners.RulesSubcategoryReliabilityDiagnosticLogs,
Description: "Azure Databricks should have diagnostic settings enabled",
Severity: scanners.SeverityMedium,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
service := target.(*armdatabricks.Workspace)
_, ok := scanContext.DiagnosticsSettings[strings.ToLower(*service.ID)]
return !ok, ""
},
Url: "https://learn.microsoft.com/en-us/azure/databricks/administration-guide/account-settings/audit-log-delivery",
Field: scanners.OverviewFieldDiagnostics,
},
"dbw-003": {
Id: "dbw-003",
Category: scanners.RulesCategoryReliability,
Subcategory: scanners.RulesSubcategoryReliabilitySLA,
Description: "Azure Databricks should have a SLA",
Severity: scanners.SeverityHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
return false, "99.95%"
},
Url: "https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services",
Field: scanners.OverviewFieldSLA,
},
"dbw-004": {
Id: "dbw-004",
Category: scanners.RulesCategorySecurity,
Subcategory: scanners.RulesSubcategorySecurityPrivateEndpoint,
Description: "Azure Databricks should have private endpoints enabled",
Severity: scanners.SeverityHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
i := target.(*armdatabricks.Workspace)
pe := len(i.Properties.PrivateEndpointConnections) > 0
return !pe, ""
},
Url: "https://learn.microsoft.com/en-us/azure/databricks/administration-guide/cloud-configurations/azure/private-link",
Field: scanners.OverviewFieldPrivate,
},
"dbw-005": {
Id: "dbw-005",
Category: scanners.RulesCategoryReliability,
Subcategory: scanners.RulesSubcategoryReliabilitySKU,
Description: "Azure Databricks SKU",
Severity: scanners.SeverityHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
i := target.(*armdatabricks.Workspace)
return false, string(*i.SKU.Name)
},
Url: "https://azure.microsoft.com/en-us/pricing/details/databricks/",
Field: scanners.OverviewFieldSKU,
},
"dbw-006": {
Id: "dbw-006",
Category: scanners.RulesCategoryOperationalExcellence,
Subcategory: scanners.RulesSubcategoryOperationalExcellenceCAF,
Description: "Azure Databricks Name should comply with naming conventions",
Severity: scanners.SeverityLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armdatabricks.Workspace)
caf := strings.HasPrefix(*c.Name, "dbw")
return !caf, ""
},
Url: "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations",
Field: scanners.OverviewFieldCAF,
},
"dbw-007": {
Id: "dbw-007",
Category: scanners.RulesCategorySecurity,
Subcategory: scanners.RulesSubcategorySecurityIdentity,
Description: "Azure Databricks should have the Public IP disabled",
Severity: scanners.SeverityMedium,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armdatabricks.Workspace)
broken := c.Properties.Parameters.EnableNoPublicIP != nil && c.Properties.Parameters.EnableNoPublicIP.Value == ref.Of(true)
return broken, ""
},
Url: "https://learn.microsoft.com/en-us/azure/databricks/security/network/secure-cluster-connectivity",
},
}
}
Loading

0 comments on commit 5d9f2fb

Please sign in to comment.