Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add synapse workspace & synapse spark pool cmd's #204

Merged
merged 11 commits into from
Apr 23, 2024
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ To learn more about the recommendations used by **Azure Quick Review (azqr)**, y
* Azure SignalR Service
* Azure SQL Database
* Azure Storage Account
* Azure Synapse Analytics Workspace
* Azure Synapse Spark Pool
* Azure Synapse Dedicated SQL Pool
* Azure Traffic Manager
* Azure Virtual Machine
* Azure Virtual Network
Expand Down
28 changes: 28 additions & 0 deletions cmd/azqr/synw.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/synw"
"github.com/spf13/cobra"
)

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

var synwCmd = &cobra.Command{
Use: "synw",
Short: "Scan Azure Synapse Workspace",
Long: "Scan Azure Synapse Workspace",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
serviceScanners := []scanners.IAzureScanner{
&synw.SynapseWorkspaceScanner{},
}

scan(cmd, serviceScanners)
},
}
3 changes: 3 additions & 0 deletions docs/content/en/docs/Overview/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ To learn more about the recommendations used by **Azure Quick Review (azqr)**, y
* Azure SignalR Service
* Azure SQL Database
* Azure Storage Account
* Azure Synapse Analytics Workspace
* Azure Synapse Spark Pool
* Azure Synapse Dedicated SQL Pool
* Azure Traffic Manager
* Azure Virtual Machine
* Azure Virtual Network
Expand Down
13 changes: 13 additions & 0 deletions docs/content/en/docs/Recommendations/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,16 @@ Azure Quick Review checks the following recommendations for Azure resources. The
306 | High Availability | High | Web Pub Sub SKU | [Learn](https://azure.microsoft.com/en-us/pricing/details/web-pubsub/)
307 | Governance | Low | Web Pub Sub Name should comply with naming conventions | [Learn](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations)
308 | Governance | Low | Web Pub Sub should have tags | [Learn](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json)
309 | Monitoring and Alerting | Low | Azure Synapse Workspace should have diagnostic settings enabled | [Learn](https://learn.microsoft.com/en-us/azure/synapse-analytics/monitor-synapse-analytics)
310 | Security | High | Azure Synapse Workspace should have private endpoints enabled | [Learn](https://learn.microsoft.com/en-us/azure/synapse-analytics/security/synapse-workspace-managed-private-endpoints)
311 | High Availability | High | Azure Synapse Workspace SLA | [Learn](https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services)
312 | Governance | Low | Azure Synapse Workspace Name should comply with naming conventions | [Learn](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations)
313 | Governance | Low | Azure Synapse Workspace should have tags | [Learn](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json)
312 | Security | High | Azure Synapse Workspace should establish network segmentation boundaries | [Learn](https://learn.microsoft.com/en-us/security/benchmark/azure/baselines/azure-synapse-analytics-security-baseline?toc=%2Fazure%2Fsynapse-analytics%2Ftoc.json)
313 | Security | High | Azure Synapse Workspace should disable public network access | [Learn](https://learn.microsoft.com/en-us/security/benchmark/azure/baselines/azure-synapse-analytics-security-baseline?toc=%2Fazure%2Fsynapse-analytics%2Ftoc.json)
314 | High Availability | High | Azure Synapse Spark Pool SLA | [Learn](https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services)
315 | Governance | Low | Azure Synapse Spark Pool Name should comply with naming conventions | [Learn](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations)
316 | Governance | Low | Azure Synapse Spark Pool should have tags | [Learn](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json)
317 | High Availability | High | Azure Synapse Dedicated SQL Pool SLA | [Learn](https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services)
318 | Governance | Low | Azure Synapse Dedicated SQL Pool Name should comply with naming conventions | [Learn](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations)
319 | Governance | Low | Azure Synapse Dedicated SQL Pool should have tags | [Learn](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json)
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/sql/armsql v1.2.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription v1.2.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/synapse/armsynapse v0.8.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/trafficmanager/armtrafficmanager v1.3.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/webpubsub/armwebpubsub v1.2.0
github.com/rs/zerolog v1.31.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0/go.mod h1:T5RfihdXtBDxt1Ch2wobif3TvzTdumDy29kahv6AV9A=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription v1.2.0 h1:UrGzkHueDwAWDdjQxC+QaXHd4tVCkISYE9j7fSSXF8k=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/subscription/armsubscription v1.2.0/go.mod h1:qskvSQeW+cxEE2bcKYyKimB1/KiQ9xpJ99bcHY0BX6c=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/synapse/armsynapse v0.8.0 h1:IKCilT2DdxjeCXhiCIZb5hywpA1KDGKwpdA1WL20wT0=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/synapse/armsynapse v0.8.0/go.mod h1:IzuvA34YNVnlifc1+KhCouAKEf1VYzV439FOpyfTHzA=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/trafficmanager/armtrafficmanager v1.3.0 h1:e3kTG23M5ps+DjvPolK4dcgohDY8sHsXU7zrdHj1WzY=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/trafficmanager/armtrafficmanager v1.3.0/go.mod h1:Os5dq8Cvvz97rJauZhZJAfKHN+OEvF/0nVmHzF4aVys=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/webpubsub/armwebpubsub v1.2.0 h1:U+zDy6lU9scW8b58JpcQAlI+lsitiVSjz/RzBqbS5gM=
Expand Down
2 changes: 2 additions & 0 deletions internal/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import (
"github.com/Azure/azqr/internal/scanners/sigr"
"github.com/Azure/azqr/internal/scanners/sql"
"github.com/Azure/azqr/internal/scanners/st"
"github.com/Azure/azqr/internal/scanners/synw"
"github.com/Azure/azqr/internal/scanners/traf"
"github.com/Azure/azqr/internal/scanners/vm"
"github.com/Azure/azqr/internal/scanners/vnet"
Expand Down Expand Up @@ -471,6 +472,7 @@ func GetScanners() []scanners.IAzureScanner {
&sb.ServiceBusScanner{},
&sigr.SignalRScanner{},
&sql.SQLScanner{},
&synw.SynapseWorkspaceScanner{},
&traf.TrafficManagerScanner{},
&st.StorageScanner{},
&vm.VirtualMachineScanner{},
Expand Down
182 changes: 182 additions & 0 deletions internal/scanners/synw/rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package synw

import (
"strings"

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

// GetRules - Returns the rules for the SynapseWorkspaceScanner
func (a *SynapseWorkspaceScanner) GetRules() map[string]scanners.AzureRule {
result := a.getWorkspaceRules()
for k, v := range a.getSparkPoolRules() {
result[k] = v
}
for k, v := range a.getSqlPoolRules() {
result[k] = v
}
return result
}
func (a *SynapseWorkspaceScanner) getWorkspaceRules() map[string]scanners.AzureRule {
return map[string]scanners.AzureRule{
"synw-001": {
Id: "synw-001",
Category: scanners.RulesCategoryMonitoringAndAlerting,
Recommendation: "Azure Synapse Workspace should have diagnostic settings enabled",
Impact: scanners.ImpactLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
service := target.(*armsynapse.Workspace)
_, ok := scanContext.DiagnosticsSettings[strings.ToLower(*service.ID)]
return !ok, ""
},
Url: "https://learn.microsoft.com/en-us/azure/data-factory/monitor-configure-diagnostics",
},
"synw-002": {
Id: "synw-002",
Category: scanners.RulesCategorySecurity,
Recommendation: "Azure Synapse Workspace should have private endpoints enabled",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
i := target.(*armsynapse.Workspace)
pe := len(i.Properties.PrivateEndpointConnections) > 0
return !pe, ""
},
Url: "https://learn.microsoft.com/en-us/azure/synapse-analytics/security/synapse-workspace-managed-private-endpoints",
},
"synw-003": {
Id: "synw-003",
Category: scanners.RulesCategoryHighAvailability,
Recommendation: "Azure Synapse Workspace SLA",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
return false, "99.9%"
},
Url: "https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services",
},
"synw-004": {
Id: "synw-004",
Category: scanners.RulesCategoryGovernance,
Recommendation: "Azure Synapse Workspace Name should comply with naming conventions",
Impact: scanners.ImpactLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armsynapse.Workspace)
caf := strings.HasPrefix(*c.Name, "synw")
return !caf, ""
},
Url: "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations",
},
"synw-005": {
Id: "synw-005",
Category: scanners.RulesCategoryGovernance,
Recommendation: "Azure Synapse Workspace should have tags",
Impact: scanners.ImpactLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armsynapse.Workspace)
return len(c.Tags) == 0, ""
},
Url: "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json",
},
"synw-006": {
Id: "synw-006",
Category: scanners.RulesCategorySecurity,
Recommendation: "Azure Synapse Workspace should establish network segmentation boundaries",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armsynapse.Workspace)
return *c.Properties.ManagedVirtualNetwork != "default", ""
},
Url: "https://learn.microsoft.com/en-us/security/benchmark/azure/baselines/azure-synapse-analytics-security-baseline?toc=%2Fazure%2Fsynapse-analytics%2Ftoc.json",
},
"synw-007": {
Id: "synw-007",
Category: scanners.RulesCategorySecurity,
Recommendation: "Azure Synapse Workspace should disable public network access",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armsynapse.Workspace)
return string(*c.Properties.PublicNetworkAccess) == "Enabled", ""
},
Url: "https://learn.microsoft.com/en-us/security/benchmark/azure/baselines/azure-synapse-analytics-security-baseline?toc=%2Fazure%2Fsynapse-analytics%2Ftoc.json",
},
}
}

func (a *SynapseWorkspaceScanner) getSparkPoolRules() map[string]scanners.AzureRule {
return map[string]scanners.AzureRule{
"synsp-001": {
Id: "synsp-001",
Category: scanners.RulesCategoryGovernance,
Recommendation: "Azure Synapse Spark Pool Name should comply with naming conventions",
Impact: scanners.ImpactLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armsynapse.BigDataPoolResourceInfo)
caf := strings.HasPrefix(*c.Name, "synsp")
return !caf, ""
},
Url: "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations",
},
"synsp-002": {
Id: "synsp-002",
Category: scanners.RulesCategoryHighAvailability,
Recommendation: "Azure Synapse Spark Pool SLA",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
return false, "99.9%"
},
Url: "https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services",
},
"synsp-003": {
Id: "synsp-003",
Category: scanners.RulesCategoryGovernance,
Recommendation: "Azure Synapse Spark Pool should have tags",
Impact: scanners.ImpactLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armsynapse.BigDataPoolResourceInfo)
return len(c.Tags) == 0, ""
},
Url: "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json",
},
}
}

func (a *SynapseWorkspaceScanner) getSqlPoolRules() map[string]scanners.AzureRule {
return map[string]scanners.AzureRule{
"syndp-001": {
Id: "syndp-001",
Category: scanners.RulesCategoryGovernance,
Recommendation: "Azure Synapse Dedicated SQL Pool Name should comply with naming conventions",
Impact: scanners.ImpactLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armsynapse.SQLPool)
caf := strings.HasPrefix(*c.Name, "syndp")
return !caf, ""
},
Url: "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations",
},
"syndp-002": {
Id: "syndp-002",
Category: scanners.RulesCategoryHighAvailability,
Recommendation: "Azure Synapse Dedicated SQL Pool SLA",
Impact: scanners.ImpactHigh,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
return false, "99.9%"
},
Url: "https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services",
},
"syndp-003": {
Id: "syndp-003",
Category: scanners.RulesCategoryGovernance,
Recommendation: "Azure Synapse Dedicated SQL Pool should have tags",
Impact: scanners.ImpactLow,
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) {
c := target.(*armsynapse.SQLPool)
return len(c.Tags) == 0, ""
},
Url: "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json",
},
}
}
Loading
Loading