-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: add Azure Virtual Network Gateway scanner (#237)
add Azure Virtual Network Gateway scanner --------- Co-authored-by: Seppe Van WInkel <van.winkel.seppe@me.com>
- Loading branch information
1 parent
a3c2156
commit 9076e3d
Showing
8 changed files
with
341 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/vgw" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
func init() { | ||
scanCmd.AddCommand(vgwCmd) | ||
} | ||
|
||
var vgwCmd = &cobra.Command{ | ||
Use: "vgw", | ||
Short: "Scan Virtual Network Gateway", | ||
Long: "Scan Virtual Network Gateway", | ||
Args: cobra.NoArgs, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
serviceScanners := []scanners.IAzureScanner{ | ||
&vgw.VirtualNetworkGatewayScanner{}, | ||
} | ||
|
||
scan(cmd, serviceScanners) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
package vgw | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/Azure/azqr/internal/scanners" | ||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5" | ||
) | ||
|
||
// GetRules - Returns the rules for the VirtualNetworkGatewayScanner | ||
func (a *VirtualNetworkGatewayScanner) GetRules() map[string]scanners.AzureRule { | ||
return a.GetVirtualNetworkGatewayRules() | ||
} | ||
|
||
// GetVirtualNetworkGatewayRules - Returns the rules for the VirtualNetworkGatewayScanner | ||
func (a *VirtualNetworkGatewayScanner) GetVirtualNetworkGatewayRules() map[string]scanners.AzureRule { | ||
return map[string]scanners.AzureRule{ | ||
"vgw-001": { | ||
Id: "vgw-001", | ||
Category: scanners.RulesCategoryMonitoringAndAlerting, | ||
Recommendation: "Virtual Network Gateway should have diagnostic settings enabled", | ||
Impact: scanners.ImpactLow, | ||
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) { | ||
service := target.(*armnetwork.VirtualNetworkGateway) | ||
_, ok := scanContext.DiagnosticsSettings[strings.ToLower(*service.ID)] | ||
return !ok, "" | ||
}, | ||
Url: "https://learn.microsoft.com/en-us/azure/vpn-gateway/monitor-vpn-gateway", | ||
}, | ||
"vgw-002": { | ||
Id: "vgw-002", | ||
Category: scanners.RulesCategoryGovernance, | ||
Recommendation: "Virtual Network Gateway Name should comply with naming conventions", | ||
Impact: scanners.ImpactLow, | ||
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) { | ||
c := target.(*armnetwork.VirtualNetworkGateway) | ||
switch *c.Properties.GatewayType { | ||
case armnetwork.VirtualNetworkGatewayTypeVPN: | ||
return !strings.HasPrefix(*c.Name, "vpng"), "" | ||
case armnetwork.VirtualNetworkGatewayTypeExpressRoute: | ||
return !strings.HasPrefix(*c.Name, "ergw"), "" | ||
default: | ||
return !strings.HasPrefix(*c.Name, "lgw"), "" | ||
} | ||
}, | ||
Url: "https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations", | ||
}, | ||
"vgw-003": { | ||
Id: "vgw-003", | ||
Category: scanners.RulesCategoryGovernance, | ||
Recommendation: "Virtual Network Gateway should have tags", | ||
Impact: scanners.ImpactLow, | ||
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) { | ||
c := target.(*armnetwork.VirtualNetworkGateway) | ||
return len(c.Tags) == 0, "" | ||
}, | ||
Url: "https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json", | ||
}, | ||
"vgw-004": { | ||
Id: "vgw-004", | ||
Category: scanners.RulesCategoryHighAvailability, | ||
Recommendation: "Virtual Network Gateway should have a SLA", | ||
Impact: scanners.ImpactHigh, | ||
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) { | ||
g := target.(*armnetwork.VirtualNetworkGateway) | ||
sku := string(*g.Properties.SKU.Tier) | ||
sla := "99.9%" | ||
if sku != string(armnetwork.VirtualNetworkGatewaySKUTierBasic) { | ||
sla = "99.95%" | ||
} | ||
return false, sla | ||
}, | ||
Url: "https://www.microsoft.com/licensing/docs/view/Service-Level-Agreements-SLA-for-Online-Services", | ||
}, | ||
"vgw-005": { | ||
Id: "vgw-005", | ||
Category: scanners.RulesCategoryHighAvailability, | ||
Recommendation: "Storage should have availability zones enabled", | ||
Impact: scanners.ImpactHigh, | ||
Eval: func(target interface{}, scanContext *scanners.ScanContext) (bool, string) { | ||
g := target.(*armnetwork.VirtualNetworkGateway) | ||
sku := string(*g.Properties.SKU.Name) | ||
return !strings.HasSuffix(strings.ToLower(sku), "az"), "" | ||
}, | ||
Url: "https://learn.microsoft.com/en-us/azure/vpn-gateway/create-zone-redundant-vnet-gateway", | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
package vgw | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/Azure/azqr/internal/scanners" | ||
"github.com/Azure/azqr/internal/to" | ||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v5" | ||
) | ||
|
||
func TestVirtualNetworkGatewayScanner_Rules(t *testing.T) { | ||
type fields struct { | ||
rule string | ||
target interface{} | ||
scanContext *scanners.ScanContext | ||
} | ||
type want struct { | ||
broken bool | ||
result string | ||
} | ||
tests := []struct { | ||
name string | ||
fields fields | ||
want want | ||
}{ | ||
{ | ||
name: "VirtualNetworkGatewayScanner DiagnosticSettings", | ||
fields: fields{ | ||
rule: "vgw-001", | ||
target: &armnetwork.VirtualNetworkGateway{ | ||
ID: to.Ptr("test"), | ||
}, | ||
scanContext: &scanners.ScanContext{ | ||
DiagnosticsSettings: map[string]bool{ | ||
"test": true, | ||
}, | ||
}, | ||
}, | ||
want: want{ | ||
broken: false, | ||
result: "", | ||
}, | ||
}, | ||
{ | ||
name: "VirtualNetworkGatewayScanner CAF", | ||
fields: fields{ | ||
rule: "vgw-002", | ||
target: &armnetwork.VirtualNetworkGateway{ | ||
Name: to.Ptr("vpng-test"), | ||
Properties: &armnetwork.VirtualNetworkGatewayPropertiesFormat{ | ||
GatewayType: to.Ptr(armnetwork.VirtualNetworkGatewayTypeVPN), | ||
}, | ||
}, | ||
scanContext: &scanners.ScanContext{}, | ||
}, | ||
want: want{ | ||
broken: false, | ||
result: "", | ||
}, | ||
}, | ||
{ | ||
name: "VirtualNetworkGatewayScanner SLA 99.9%", | ||
fields: fields{ | ||
rule: "vgw-004", | ||
target: &armnetwork.VirtualNetworkGateway{ | ||
Properties: &armnetwork.VirtualNetworkGatewayPropertiesFormat{ | ||
SKU: &armnetwork.VirtualNetworkGatewaySKU{ | ||
Tier: to.Ptr(armnetwork.VirtualNetworkGatewaySKUTierBasic), | ||
}}, | ||
}, | ||
scanContext: &scanners.ScanContext{}, | ||
}, | ||
want: want{ | ||
broken: false, | ||
result: "99.9%", | ||
}, | ||
}, | ||
{ | ||
name: "VirtualNetworkGatewayScanner SLA 99.9%", | ||
fields: fields{ | ||
rule: "vgw-004", | ||
target: &armnetwork.VirtualNetworkGateway{ | ||
Properties: &armnetwork.VirtualNetworkGatewayPropertiesFormat{ | ||
SKU: &armnetwork.VirtualNetworkGatewaySKU{ | ||
Tier: to.Ptr(armnetwork.VirtualNetworkGatewaySKUTierErGw1AZ), | ||
}}, | ||
}, | ||
scanContext: &scanners.ScanContext{}, | ||
}, | ||
want: want{ | ||
broken: false, | ||
result: "99.95%", | ||
}, | ||
}, | ||
{ | ||
name: "VirtualNetworkGatewayScanner without AZ", | ||
fields: fields{ | ||
rule: "vgw-005", | ||
target: &armnetwork.VirtualNetworkGateway{ | ||
Properties: &armnetwork.VirtualNetworkGatewayPropertiesFormat{ | ||
SKU: &armnetwork.VirtualNetworkGatewaySKU{ | ||
Name: to.Ptr(armnetwork.VirtualNetworkGatewaySKUNameBasic), | ||
}}, | ||
}, | ||
scanContext: &scanners.ScanContext{}, | ||
}, | ||
want: want{ | ||
broken: true, | ||
result: "", | ||
}, | ||
}, | ||
{ | ||
name: "VirtualNetworkGatewayScanner with AZ", | ||
fields: fields{ | ||
rule: "vgw-005", | ||
target: &armnetwork.VirtualNetworkGateway{ | ||
Properties: &armnetwork.VirtualNetworkGatewayPropertiesFormat{ | ||
SKU: &armnetwork.VirtualNetworkGatewaySKU{ | ||
Name: to.Ptr(armnetwork.VirtualNetworkGatewaySKUNameErGw1AZ), | ||
}}, | ||
}, | ||
scanContext: &scanners.ScanContext{}, | ||
}, | ||
want: want{ | ||
broken: false, | ||
result: "", | ||
}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
s := &VirtualNetworkGatewayScanner{} | ||
rules := s.GetVirtualNetworkGatewayRules() | ||
b, w := rules[tt.fields.rule].Eval(tt.fields.target, tt.fields.scanContext) | ||
got := want{ | ||
broken: b, | ||
result: w, | ||
} | ||
if !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("VirtualNetworkGatewayScanner Rule.Eval() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.