Add additional AKS rules and fixes (#192)

This commit is contained in:
Bernie White 2019-12-07 21:56:38 +10:00 коммит произвёл GitHub
Родитель b6eebdbd94
Коммит be63f9d135
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
58 изменённых файлов: 895 добавлений и 207 удалений

Просмотреть файл

@ -2,6 +2,18 @@
## Unreleased
- Fixed null reference without parameters file. [#189](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/189)
- Added new rule to check presence of classic Co-Administrators. [#188](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/188)
- Added new rule to check AKS node pool version matches cluster version. [#186](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/186)
- Added new rule to check AKS clusters use pod security policies. [#142](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/142)
- Added new rule to check AKS clusters use network policies. [#143](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/143)
- Added new rule to check AKS node pools use scale sets. [#187](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/187)
- Added new baseline to include rules for preview features. [#190](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/190)
- Updated `Azure.AKS.Version` to check for node pool version. [#191](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/191)
- **Breaking change**: RBAC rules have been renamed from `Azure.Subscription.*` to `Azure.RBAC.*`. [#119](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/119)
- **Breaking change**: Security Center rules have been renamed from `Azure.Subscription.*` to `Azure.SecureCenter.*`. [#119](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/119)
- **Breaking change**: Renamed default baseline from `Azure.SubscriptionDefault` to `Azure.Default`. [#190](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/190)
## v0.6.0
What's changed since v0.5.0:

Просмотреть файл

@ -0,0 +1,36 @@
---
severity: Important
category: Security configuration
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.AKS.NetworkPolicy.md
---
# AKS clusters use Azure Network Policies
## SYNOPSIS
Deploy AKS clusters with Azure Network Policies enabled.
## DESCRIPTION
By default, all pods in an AKS cluster can send and receive traffic without limitations.
Network Policy defines access policies for limiting network communication of Pods.
For improved security, define network policy rules to control the flow of traffic.
For example, only permit backend components to receive traffic from frontend components.
To use Network Policy it must be enabled at cluster deployment time.
AKS supports two implementations of network policies, Azure Network Policies and Calico Network Policies.
Azure Network Policies are supported by Azure support and engineering teams.
## RECOMMENDATION
Azure Network Policies improve cluster and workload security by limiting network communication.
Network Policy is a deployment time configuration.
Consider redeploying the AKS cluster with Network Policy enabled.
## LINKS
- [Secure traffic between pods using network policies in Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/use-network-policies)
- [Best practices for network connectivity and security in Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/operator-best-practices-network#control-traffic-flow-with-network-policies)
- [Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/)

Просмотреть файл

@ -0,0 +1,32 @@
---
severity: Important
category: Security configuration
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.AKS.PodSecurityPolicy.md
---
# AKS cluster use Pod Security Policies
## SYNOPSIS
Configure AKS non-production clusters to use Pod Security Policies (Preview).
## DESCRIPTION
Pod Security Polices are a preview feature that can be enabled on AKS clusters after configuration.
Pod Security Polices limit pods from requesting or performing some privileged actions.
Based on the policy the pod specification may be updated with additional controls or blocked completely.
Configure Pod Security Policies first, before enabling the feature.
Enabling the feature before configuring Pod Security Polices, will block pod creation.
## RECOMMENDATION
Consider deploying AKS clusters, configuring Pod Security Polices then enabling on non-production clusters.
Only enable Pod Security Policies after configuring policies.
Pod Security Policies are currently in preview.
## LINK
- [Secure your cluster using pod security policies in Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/use-pod-security-policies)
- [Pod Security Policies](https://kubernetes.io/docs/concepts/policy/pod-security-policy/)

Просмотреть файл

@ -0,0 +1,30 @@
---
severity: Important
category: Scalability
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.AKS.PoolScaleSet.md
---
# AKS clusters use VM scale sets
## SYNOPSIS
Deploy AKS clusters with nodes pools based on VM scale sets.
## DESCRIPTION
When deploying AKS clusters, Azure node pool VMs can be deployed using Availability Sets or VM Scale Sets.
New AKS clusters default to VM scale set node pools.
Deploying AKS clusters with scale set node pools is required for some cluster features such as multiple node pools and cluster autoscaler.
## RECOMMENDATION
Multiple node pools and the cluster autoscaler can be used to improve the scalability and performance of a cluster while minimizing cost.
Using VM scale sets is a deployment time configuration.
Consider redeploying the AKS cluster with VM Scale Sets instead of Availability Sets.
## LINKS
- [Create and manage multiple node pools for a cluster in Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools)
- [Cluster autoscaler](https://docs.microsoft.com/en-us/azure/aks/concepts-scale#cluster-autoscaler)

Просмотреть файл

@ -0,0 +1,28 @@
---
severity: Important
category: Operations management
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.AKS.PoolVersion.md
---
# Upgrade AKS node pool version
## SYNOPSIS
AKS node pools should match Kubernetes control plane version.
## DESCRIPTION
AKS supports multiple node pools.
In a multi-node pool configuration, it is possible that the control plane and node pools could be running a different version of Kubernetes.
Different versions of Kubernetes between the control plane and node pools is intended as a short term option to allow rolling upgrades.
For general operation, the control plane and node pool Kubernetes versions should match.
## RECOMMENDATION
Consider upgrading node pools to match AKS control plan version.
## LINKS
- [Upgrade a cluster control plane with multiple node pools](https://docs.microsoft.com/en-us/azure/aks/use-multiple-node-pools#upgrade-a-cluster-control-plane-with-multiple-node-pools)
- [Supported Kubernetes versions in Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/supported-kubernetes-versions).

Просмотреть файл

@ -5,18 +5,26 @@ online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/do
ms-content-id: 61ff3a23-9bfd-4e91-8959-798b43237775
---
# Azure.AKS.UseRBAC
# AKS clusters use RBAC
## SYNOPSIS
AKS cluster should use role-based access control (RBAC).
Deploy AKS cluster with role-based access control (RBAC) enabled.
## DESCRIPTION
AKS cluster should use role-based access control (RBAC).
AKS supports granting access to cluster resources using role-based access control (RBAC).
Additionally Azure Active Directory (AAD) integration with AKS allows, RBAC to be granted based on AAD user or group.
## RECOMMENDATION
Azure AD integration with AKS provides granular access control for Kubernetes resources using RBAC.
RBAC is a deployment time configuration. Consider redeploying the AKS cluster with RBAC enabled.
RBAC is a deployment time configuration.
Consider redeploying the AKS cluster with RBAC enabled.
## LINKS
- [Access and identity options for Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/concepts-identity#azure-active-directory-integration)
- [Best practices for authentication and authorization in Azure Kubernetes Service (AKS)](https://docs.microsoft.com/en-us/azure/aks/operator-best-practices-identity#use-azure-active-directory)
- [Using RBAC Authorization](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)

Просмотреть файл

@ -5,20 +5,24 @@ online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/do
ms-content-id: b0bd4e66-af2f-4d0a-82ae-e4738418bb7e
---
# Azure.AKS.Version
# Upgrade Kubernetes version
## SYNOPSIS
AKS clusters should meet the minimum version.
AKS control plane and nodes pools should use a current stable release.
## DESCRIPTION
The Kubernetes support policy for AKS includes four stable minor releases, and two patch releases for each minor version.
The AKS support policy for Kubernetes is include N-2 stable minor releases.
Additionally two patch releases for each minor version are supported.
A list of available Kubernetes versions can be found using the `az aks get-versions -o table --location <location>` CLI command.
## RECOMMENDATION
Upgrade Kubernetes to the latest stable version of Kubernetes.
Consider upgrading AKS control plan and nodes pools to the latest stable version of Kubernetes.
For more information see [Supported Kubernetes versions in Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/supported-kubernetes-versions).
## LINKS
- [Supported Kubernetes versions in Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/supported-kubernetes-versions).
- [Support policies for Azure Kubernetes Service](https://docs.microsoft.com/en-us/azure/aks/support-policies)

Просмотреть файл

@ -0,0 +1,30 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.RBAC.CoAdministrator.md
---
# Use role-based access control
## SYNOPSIS
Delegate access to manage Azure resources using role-based access control (RBAC).
## DESCRIPTION
Use of Co-administrator is intended to support management of resources deployed using the Classic deployment model.
Resources deployed in the Resource Manager model do not require delegation of Co-administrators.
Azure RBAC provides greater flexibility and control providing over 100 built-in roles.
Additionally RBAC works with advanced advanced security features like Privileged Identity Management (PIM).
## RECOMMENDATION
Consider delegating access to manage Azure resources using RBAC instead of classic Co-administrator roles.
Limit delegation of Co-administrator roles only to subscription that contain resources deployed in the Classic deployment model.
## LINKS
- [Azure classic subscription administrators](https://docs.microsoft.com/en-us/azure/role-based-access-control/classic-administrators)
- [Classic subscription administrator roles, Azure RBAC roles, and Azure AD administrator roles](https://docs.microsoft.com/en-us/azure/role-based-access-control/rbac-and-directory-admin-roles)
- [What is Azure AD Privileged Identity Management?](https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-configure)

Просмотреть файл

@ -1,7 +1,7 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.Subscription.LimitMGDelegation.md
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.RBAC.LimitMGDelegation.md
ms-content-id: 0f0a1cc8-9528-46b7-8f31-b9fe76cc0d66
---
@ -13,10 +13,12 @@ Limit Role-Base Access Control (RBAC) inheritance from Management Groups.
## DESCRIPTION
RBAC in Azure inherits from management group to subscription to resource group to resource. Management group RBAC assignments have broad impact.
RBAC in Azure inherits from management group to subscription to resource group to resource.
Management group RBAC assignments have broad impact.
## RECOMMENDATION
Consider limiting the number of assignment inherited from Management Groups by scoping permission to individual Resource Group.
Azure Blueprints can be used to rollout standard RBAC assignments to common resources. Additionally RBAC assignments can be deployed using Azure Resource Manager templates.
Azure Blueprints can be used to rollout standard RBAC assignments to common resources.
Additionally RBAC assignments can be deployed using Azure Resource Manager templates.

Просмотреть файл

@ -1,7 +1,7 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.Subscription.LimitOwner.md
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.RBAC.LimitOwner.md
ms-content-id: 43075204-e28b-46a0-90a0-ea5c3b74e9ab
---

Просмотреть файл

@ -1,7 +1,7 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.Subscription.UseGroups.md
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.RBAC.UseGroups.md
ms-content-id: 818cc242-5912-44b6-b3dc-461822079522
---

Просмотреть файл

@ -1,7 +1,7 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.Subscription.UseRGDelegation.md
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.RBAC.UseRGDelegation.md
ms-content-id: b31d32cc-1e9f-4ab8-93ab-1cd98354ad15
---

Просмотреть файл

@ -0,0 +1,24 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.SecurityCenter.Contact.md
ms-content-id: 18fcf75f-a5e6-4a34-baba-74bd49502cd7
---
# Set Security Center contact details
## SYNOPSIS
Security Center email and phone contact details should be set.
## DESCRIPTION
Security contact details configured in Security Center are used by Microsoft to notify you in response to certain security events.
## RECOMMENDATION
Consider configuring Security Center email and phone contact details.
## LINK
- [Provide security contact details in Azure Security Center](https://docs.microsoft.com/en-us/azure/security-center/security-center-provide-security-contact-details)

Просмотреть файл

@ -0,0 +1,27 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.SecurityCenter.Provisioning.md
ms-content-id: 966390bc-0358-43dd-8b5f-6b0ae2b16edd
---
# Enable Security Center auto-provisioning
## SYNOPSIS
Enable auto-provisioning on to improve Azure Security Center insights.
## DESCRIPTION
Select resources such as virtual machines (VMs) and VM scale sets require an agent to be installed to collect additional information from the operating system (OS).
This information is used to identify missing security updates and additional threats.
By turning auto-provisioning on, Security Center automatically deploys an Azure Monitor agent to VMs on a regular basis.
## RECOMMENDATION
Consider enabling auto-provisioning on to improve Azure Security Center insights.
## LINKS
- [Data collection in Azure Security Center](https://docs.microsoft.com/en-us/azure/security-center/security-center-enable-data-collection)

Просмотреть файл

@ -1,20 +0,0 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.Subscription.SecurityCenterContact.md
ms-content-id: 18fcf75f-a5e6-4a34-baba-74bd49502cd7
---
# Azure.Subscription.SecurityCenterContact
## SYNOPSIS
Security Center email and phone contact details should be set.
## DESCRIPTION
Security Center email and phone contact details should be set.
## RECOMMENDATION
Security Center email and phone contact details should be set.

Просмотреть файл

@ -1,20 +0,0 @@
---
severity: Important
category: Security operations
online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.Subscription.SecurityCenterProvisioning.md
ms-content-id: 966390bc-0358-43dd-8b5f-6b0ae2b16edd
---
# Azure.Subscription.SecurityCenterProvisioning
## SYNOPSIS
Enable auto-provisioning on VMs to improve Security Center insights.
## DESCRIPTION
Enable auto-provisioning on VMs to improve Security Center insights.
## RECOMMENDATION
Enable auto-provisioning on VMs to improve Security Center insights.

Просмотреть файл

@ -5,8 +5,11 @@ RuleName | Description | Category
[Azure.ACR.AdminUser](Azure.ACR.AdminUser.md) | Use Azure AD accounts instead of using the registry admin user. | Security configuration
[Azure.ACR.MinSku](Azure.ACR.MinSku.md) | ACR should use the Premium or Standard SKU for production deployments. | Performance
[Azure.AKS.MinNodeCount](Azure.AKS.MinNodeCount.md) | AKS clusters should have minimum number of nodes for failover and updates. | Reliability
[Azure.AKS.Version](Azure.AKS.Version.md) | AKS clusters should meet the minimum version. | Operations management
[Azure.AKS.UseRBAC](Azure.AKS.UseRBAC.md) | AKS cluster should use role-based access control (RBAC). | Security configuration
[Azure.AKS.Version](Azure.AKS.Version.md) | AKS control plane and nodes pools should use a current stable release. | Operations management
[Azure.AKS.PoolVersion](Azure.AKS.PoolVersion.md) | AKS node pools should match Kubernetes control plane version. | Operations management
[Azure.AKS.UseRBAC](Azure.AKS.UseRBAC.md) | Deploy AKS cluster with role-based access control (RBAC) enabled. | Security configuration
[Azure.AKS.NetworkPolicy](Azure.AKS.NetworkPolicy.md) | Deploy AKS clusters with Azure Network Policies enabled. | Security configuration
[Azure.AKS.PoolScaleSet](Azure.AKS.PoolScaleSet.md) | Deploy AKS clusters with nodes pools based on VM scale sets. | Scalability
[Azure.AppService.PlanInstanceCount](Azure.AppService.PlanInstanceCount.md) | Use an App Service Plan with at least two (2) instances. | Reliability
[Azure.AppService.MinPlan](Azure.AppService.MinPlan.md) | Use at least a Standard App Service Plan. | Performance
[Azure.AppService.ARRAffinity](Azure.AppService.ARRAffinity.md) | Disable client affinity for stateless services. | Performance
@ -35,12 +38,13 @@ RuleName | Description | Category
[Azure.Storage.SecureTransferRequired](Azure.Storage.SecureTransferRequired.md) | Storage accounts should only accept secure traffic. | Security configuration
[Azure.Storage.UseEncryption](Azure.Storage.UseEncryption.md) | Storage Service Encryption (SSE) should be enabled. | Security configuration
[Azure.Storage.SoftDelete](Azure.Storage.SoftDelete.md) | Enable soft delete on Storage Accounts. | Data recovery
[Azure.Subscription.UseGroups](Azure.Subscription.UseGroups.md) | Use groups for assigning permissions instead of individual user accounts. | Security operations
[Azure.Subscription.LimitOwner](Azure.Subscription.LimitOwner.md) | Limit the number of subscription Owners. | Security operations
[Azure.Subscription.LimitMGDelegation](Azure.Subscription.LimitMGDelegation.md) | Limit Role-Base Access Control (RBAC) inheritance from Management Groups. | Security operations
[Azure.Subscription.SecurityCenterContact](Azure.Subscription.SecurityCenterContact.md) | Security Center email and phone contact details should be set. | Security operations
[Azure.Subscription.SecurityCenterProvisioning](Azure.Subscription.SecurityCenterProvisioning.md) | Enable auto-provisioning on VMs to improve Security Center insights. | Security operations
[Azure.Subscription.UseRGDelegation](Azure.Subscription.UseRGDelegation.md) | Use RBAC assignments on resource groups instead of individual resources. | Security operations
[Azure.RBAC.UseGroups](Azure.RBAC.UseGroups.md) | Use groups for assigning permissions instead of individual user accounts. | Security operations
[Azure.RBAC.LimitOwner](Azure.RBAC.LimitOwner.md) | Limit the number of subscription Owners. | Security operations
[Azure.RBAC.LimitMGDelegation](Azure.RBAC.LimitMGDelegation.md) | Limit Role-Base Access Control (RBAC) inheritance from Management Groups. | Security operations
[Azure.RBAC.CoAdministrator](Azure.RBAC.CoAdministrator.md) | Delegate access to manage Azure resources using role-based access control (RBAC). | Security operations
[Azure.RBAC.UseRGDelegation](Azure.RBAC.UseRGDelegation.md) | Use RBAC assignments on resource groups instead of individual resources. | Security operations
[Azure.SecurityCenter.Contact](Azure.SecurityCenter.Contact.md) | Security Center email and phone contact details should be set. | Security operations
[Azure.SecurityCenter.Provisioning](Azure.SecurityCenter.Provisioning.md) | Enable auto-provisioning on VMs to improve Security Center insights. | Security operations
[Azure.VM.UseManagedDisks](Azure.VM.UseManagedDisks.md) | Virtual machines should use managed disks. | Reliability
[Azure.VM.Standalone](Azure.VM.Standalone.md) | VMs must use premium disks or use availability sets/ zones to meet SLA requirements. | Reliability
[Azure.VM.PromoSku](Azure.VM.PromoSku.md) | Virtual machines (VMs) should not use expired promotional SKU. | Cost management

Просмотреть файл

@ -101,7 +101,7 @@ task VersionModule ModuleDependencies, {
$manifest = Test-ModuleManifest -Path $manifestPath;
$requiredModules = $manifest.RequiredModules | ForEach-Object -Process {
if ($_.Name -eq 'PSRule' -and $Configuration -eq 'Release') {
@{ ModuleName = 'PSRule'; ModuleVersion = '0.10.0' }
@{ ModuleName = 'PSRule'; ModuleVersion = '0.12.0' }
}
else {
@{ ModuleName = $_.Name; ModuleVersion = $_.Version }
@ -109,7 +109,7 @@ task VersionModule ModuleDependencies, {
};
Update-ModuleManifest -Path $manifestPath -RequiredModules $requiredModules;
$manifestContent = Get-Content -Path $manifestPath -Raw;
$manifestContent = $manifestContent -replace 'PSRule = ''System.Collections.Hashtable''', 'PSRule = @{ Baseline = ''Azure.SubscriptionDefault'' }';
$manifestContent = $manifestContent -replace 'PSRule = ''System.Collections.Hashtable''', 'PSRule = @{ Baseline = ''Azure.Default'' }';
$manifestContent | Set-Content -Path $manifestPath;
}
@ -151,8 +151,8 @@ task PSScriptAnalyzer NuGet, {
# Synopsis: Install PSRule
task PSRule NuGet, {
if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.11.0 -ErrorAction Ignore)) {
Install-Module -Name PSRule -Repository PSGallery -MinimumVersion 0.11.0 -Scope CurrentUser -Force;
if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.12.0 -ErrorAction Ignore)) {
Install-Module -Name PSRule -Repository PSGallery -MinimumVersion 0.12.0 -Scope CurrentUser -Force;
}
Import-Module -Name PSRule -Verbose:$False;
}

Просмотреть файл

@ -16,7 +16,7 @@ bugs:
url: https://github.com/BernieWhite/PSRule.Rules.Azure/issues
modules:
PSRule: ^0.11.0
PSRule: ^0.12.0
tasks:
clear:

Просмотреть файл

@ -115,7 +115,7 @@ PrivateData = @{
ReleaseNotes = 'https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/CHANGELOG.md'
} # End of PSData hashtable
PSRule = @{
Baseline = 'Azure.SubscriptionDefault'
Baseline = 'Azure.Default'
}
} # End of PrivateData hashtable

Просмотреть файл

@ -538,7 +538,7 @@ function VisitSubscription {
)
process {
$resources = @();
$resources += Get-AzRoleAssignment -DefaultProfile $Context | SetResourceType 'Microsoft.Authorization/roleAssignments';
$resources += Get-AzRoleAssignment -DefaultProfile $Context -IncludeClassicAdministrators | SetResourceType 'Microsoft.Authorization/roleAssignments';
$resources += Get-AzSecurityAutoProvisioningSetting -DefaultProfile $Context | SetResourceType 'Microsoft.Security/autoProvisioningSettings';
$resources += Get-AzSecurityContact -DefaultProfile $Context | SetResourceType 'Microsoft.Security/securityContacts';
$resources += Get-AzResource -DefaultProfile $Context -ApiVersion '2018-06-01' -ResourceId "/subscriptions/$($Resource.Id)/providers/Microsoft.Security/pricings";

Просмотреть файл

@ -132,11 +132,11 @@ namespace PSRule.Rules.Azure.Pipeline
if (sourceObject == null || !(sourceObject.BaseObject is TemplateSource source))
return;
for (var i = 0; i < source.ParametersFile.Length; i++)
{
var output = ProcessTemplate(source.TemplateFile, source.ParametersFile[i]);
_Writer.Write(output, true);
}
if (source.ParametersFile == null || source.ParametersFile.Length == 0)
_Writer.Write(ProcessTemplate(source.TemplateFile, null), true);
else
for (var i = 0; i < source.ParametersFile.Length; i++)
_Writer.Write(ProcessTemplate(source.TemplateFile, source.ParametersFile[i]), true);
}
public override void End()
@ -150,7 +150,7 @@ namespace PSRule.Rules.Azure.Pipeline
if (templateObject == null)
throw new FileNotFoundException();
var parametersObject = ReadFile<JObject>(PSRuleOption.GetRootedPath(parametersFile));
var parametersObject = parametersFile != null ? ReadFile<JObject>(PSRuleOption.GetRootedPath(parametersFile)) : null;
var visitor = new RuleDataExportVisitor();
// Load context

Просмотреть файл

@ -4,4 +4,7 @@
AllowedRegionsNotConfigured = "The azureAllowedRegions option is not configured."
TcpHealthProbe = "The health probe ({0}) is using TCP."
RootHttpProbePath = "The health probe ({0}) is using '{1}'."
AKSVersion = "The Kubernetes version is v{0}."
AKSNodePoolType = "The agent pool ({0}) is not using scale sets."
AKSNodePoolVersion = "The agent pool ({0}) is running v{1}."
}

Просмотреть файл

@ -4,4 +4,7 @@
AllowedRegionsNotConfigured = "The azureAllowedRegions option is not configured."
TcpHealthProbe = "The health probe ({0}) is using TCP."
RootHttpProbePath = "The health probe ({0}) is using '{1}'."
AKSVersion = "The Kubernetes version is v{0}."
AKSNodePoolType = "The agent pool ({0}) is not using scale sets."
AKSNodePoolVersion = "The agent pool ({0}) is running v{1}."
}

Просмотреть файл

@ -2,4 +2,9 @@
MinTLSVersion = "Minimum TLS version is set to {0}."
ResourceNotTagged = "The resource is not tagged."
AllowedRegionsNotConfigured = "The azureAllowedRegions option is not configured."
TcpHealthProbe = "The health probe ({0}) is using TCP."
RootHttpProbePath = "The health probe ({0}) is using '{1}'."
AKSVersion = "The Kubernetes version is v{0}."
AKSNodePoolType = "The agent pool ({0}) is not using scale sets."
AKSNodePoolVersion = "The agent pool ({0}) is running v{1}."
}

Просмотреть файл

@ -3,11 +3,11 @@
#
# Synopsis: Use RBAC for delegating access to ACR instead of the registry admin user
Rule 'Azure.ACR.AdminUser' -Type 'Microsoft.ContainerRegistry/registries' -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.ACR.AdminUser' -Type 'Microsoft.ContainerRegistry/registries' -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
$TargetObject.Properties.adminUserEnabled -eq $False
}
# Synopsis: ACR should use the Premium or Standard SKU for production deployments
Rule 'Azure.ACR.MinSku' -Type 'Microsoft.ContainerRegistry/registries' -Tag @{ severity = 'Important'; category = 'Performance' } {
Rule 'Azure.ACR.MinSku' -Type 'Microsoft.ContainerRegistry/registries' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Performance' } {
Within 'Sku.tier' -AllowedValue 'Premium', 'Standard'
}

Просмотреть файл

@ -3,23 +3,63 @@
#
# Synopsis: AKS clusters should have minimum number of nodes for failover and updates
Rule 'Azure.AKS.MinNodeCount' -Type 'Microsoft.ContainerService/managedClusters' -Tag @{ severity = 'Important'; category = 'Reliability' } {
Recommend 'Use at least three (3) agent nodes'
Rule 'Azure.AKS.MinNodeCount' -Type 'Microsoft.ContainerService/managedClusters' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Reliability' } {
$TargetObject.Properties.agentPoolProfiles[0].count -ge 3
}
# Synopsis: AKS cluster should meet the minimum version
Rule 'Azure.AKS.Version' -Type 'Microsoft.ContainerService/managedClusters' -Tag @{ severity = 'Important'; category = 'Operations management' } {
# Synopsis: AKS clusters should meet the minimum version
Rule 'Azure.AKS.Version' -Type 'Microsoft.ContainerService/managedClusters', 'Microsoft.ContainerService/managedClusters/agentPools' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Operations management' } {
$minVersion = [Version]$Configuration.minAKSVersion
Recommend "Upgrade Kubernetes to at least $minVersion"
([Version]$TargetObject.Properties.kubernetesVersion) -ge $minVersion
if ($PSRule.TargetType -eq 'Microsoft.ContainerService/managedClusters') {
([Version]$TargetObject.Properties.kubernetesVersion) -ge $minVersion
Reason ($LocalizedData.AKSVersion -f $TargetObject.Properties.kubernetesVersion);
}
elseif ($PSRule.TargetType -eq 'Microsoft.ContainerService/managedClusters/agentPools') {
([Version]$TargetObject.Properties.orchestratorVersion) -ge $minVersion
Reason ($LocalizedData.AKSVersion -f $TargetObject.Properties.orchestratorVersion);
}
} -Configure @{ minAKSVersion = '1.14.8' }
# Synopsis: AKS agent pools should run the same Kubernetes version as the cluster
Rule 'Azure.AKS.PoolVersion' -Type 'Microsoft.ContainerService/managedClusters' -Tag @{ release = 'GA' } {
$clusterVersion = $TargetObject.Properties.kubernetesVersion
foreach ($pool in $TargetObject.Properties.agentPoolProfiles) {
$Assert.Create(($pool.orchestratorVersion -eq $clusterVersion), ($LocalizedData.AKSNodePoolVersion -f $pool.name, $pool.orchestratorVersion))
}
}
# Synopsis: AKS cluster should use role-based access control
Rule 'Azure.AKS.UseRBAC' -Type 'Microsoft.ContainerService/managedClusters' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.AKS.UseRBAC' -Type 'Microsoft.ContainerService/managedClusters' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
Exists 'Properties.enableRBAC'
$TargetObject.Properties.enableRBAC -eq $True
}
# Synopsis: AKS clusters should use pod security policies
Rule 'Azure.AKS.PodSecurityPolicy' -Type 'Microsoft.ContainerService/managedClusters' -Tag @{ release = 'preview' } {
Within 'Properties.enablePodSecurityPolicy' $True
}
# Synopsis: AKS clusters should use network policies
Rule 'Azure.AKS.NetworkPolicy' -Type 'Microsoft.ContainerService/managedClusters' -Tag @{ release = 'GA' } {
Within 'Properties.networkProfile.networkPolicy' 'azure'
}
# Synopsis: AKS node pools should use scale sets
Rule 'Azure.AKS.PoolScaleSet' -Type 'Microsoft.ContainerService/managedClusters', 'Microsoft.ContainerService/managedClusters/agentPools' -Tag @{ release = 'GA' } {
$result = $True
if ($PSRule.TargetType -eq 'Microsoft.ContainerService/managedClusters') {
$TargetObject.Properties.agentPoolProfiles | ForEach-Object {
if ($_.type -ne 'VirtualMachineScaleSets') {
$result = $False
$Assert.Fail(($LocalizedData.AKSNodePoolType -f $_.name))
}
}
}
elseif ($PSRule.TargetType -eq 'Microsoft.ContainerService/managedClusters/agentPools') {
$result = $TargetObject.Properties.type -eq 'VirtualMachineScaleSets'
if (!$result) {
$Assert.Fail(($LocalizedData.AKSNodePoolType -f $TargetObject.name))
}
}
return $result
}

Просмотреть файл

@ -3,12 +3,12 @@
#
# Synopsis: Use an App Service Plan with at least two (2) instances
Rule 'Azure.AppService.PlanInstanceCount' -Type 'Microsoft.Web/serverfarms' -Tag @{ severity = 'Single point of failure'; category = 'Reliability' } {
Rule 'Azure.AppService.PlanInstanceCount' -Type 'Microsoft.Web/serverfarms' -Tag @{ release = 'GA'; severity = 'Single point of failure'; category = 'Reliability' } {
$TargetObject.Sku.capacity -ge 2
}
# Synopsis: Use at least a Standard App Service Plan
Rule 'Azure.AppService.MinPlan' -Type 'Microsoft.Web/serverfarms' -Tag @{ severity = 'Important'; category = 'Performance' } {
Rule 'Azure.AppService.MinPlan' -Type 'Microsoft.Web/serverfarms' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Performance' } {
Recommend 'Use a Standard or high plans for production services'
($TargetObject.Sku.tier -eq 'PremiumV2') -or
@ -17,21 +17,21 @@ Rule 'Azure.AppService.MinPlan' -Type 'Microsoft.Web/serverfarms' -Tag @{ severi
}
# Synopsis: Disable client affinity for stateless services
Rule 'Azure.AppService.ARRAffinity' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' -Tag @{ severity = 'Awareness'; category = 'Performance' } {
Rule 'Azure.AppService.ARRAffinity' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Performance' } {
Recommend 'Disable ARR affinity when not required'
$TargetObject.Properties.clientAffinityEnabled -eq $False
}
# Synopsis: Use HTTPS only
Rule 'Azure.AppService.UseHTTPS' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.AppService.UseHTTPS' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
Recommend 'Disable HTTP when not required'
$TargetObject.Properties.httpsOnly -eq $True
}
# Synopsis: Use at least TLS 1.2
Rule 'Azure.AppService.MinTLS' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' {
Rule 'Azure.AppService.MinTLS' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' -Tag @{ release = 'GA' } {
$siteConfig = @($TargetObject.resources | Where-Object -FilterScript {
($_.Type -eq 'Microsoft.Web/sites/config') -or
($_.Type -eq 'Microsoft.Web/sites/slots/config')

Просмотреть файл

@ -3,6 +3,6 @@
#
# Synopsis: Consider migrating to DataFactory v2
Rule 'Azure.DataFactory.Version' -Type 'Microsoft.DataFactory/datafactories', 'Microsoft.DataFactory/factories' -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.DataFactory.Version' -Type 'Microsoft.DataFactory/datafactories', 'Microsoft.DataFactory/factories' -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
$TargetObject.ResourceType -eq 'Microsoft.DataFactory/factories'
}

Просмотреть файл

@ -3,12 +3,12 @@
#
# Synopsis: Use encrypted MySQL connections
Rule 'Azure.MySQL.UseSSL' -Type 'Microsoft.DBforMySQL/servers' -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.MySQL.UseSSL' -Type 'Microsoft.DBforMySQL/servers' -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
Within 'Properties.sslEnforcement' 'Enabled'
}
# Synopsis: Determine if there is an excessive number of firewall rules
Rule 'Azure.MySQL.FirewallRuleCount' -Type 'Microsoft.DBforMySQL/servers' -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.MySQL.FirewallRuleCount' -Type 'Microsoft.DBforMySQL/servers' -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
Recommend 'MySQL Server has > 10 firewall rules, some rules may not be needed';
$firewallRules = @($TargetObject.resources | Where-Object -FilterScript {
@ -18,7 +18,7 @@ Rule 'Azure.MySQL.FirewallRuleCount' -Type 'Microsoft.DBforMySQL/servers' -Tag @
}
# Synopsis: Determine if access from Azure services is required
Rule 'Azure.MySQL.AllowAzureAccess' -Type 'Microsoft.DBforMySQL/servers' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.MySQL.AllowAzureAccess' -Type 'Microsoft.DBforMySQL/servers' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$firewallRules = @($TargetObject.resources | Where-Object -FilterScript {
$_.Type -eq 'Microsoft.DBforMySQL/servers/firewallRules' -and
(
@ -30,7 +30,7 @@ Rule 'Azure.MySQL.AllowAzureAccess' -Type 'Microsoft.DBforMySQL/servers' -Tag @{
}
# Synopsis: Determine if there is an excessive number of permitted IP addresses
Rule 'Azure.MySQL.FirewallIPRange' -Type 'Microsoft.DBforMySQL/servers' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.MySQL.FirewallIPRange' -Type 'Microsoft.DBforMySQL/servers' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$summary = GetIPAddressSummary
$summary.Public -le 10;
}

Просмотреть файл

@ -3,12 +3,12 @@
#
# Synopsis: Use encrypted PostgreSQL connections
Rule 'Azure.PostgreSQL.UseSSL' -Type 'Microsoft.DBforPostgreSQL/servers' -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.PostgreSQL.UseSSL' -Type 'Microsoft.DBforPostgreSQL/servers' -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
Within 'Properties.sslEnforcement' 'Enabled'
}
# Synopsis: Determine if there is an excessive number of firewall rules
Rule 'Azure.PostgreSQL.FirewallRuleCount' -Type 'Microsoft.DBforPostgreSQL/servers' -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.PostgreSQL.FirewallRuleCount' -Type 'Microsoft.DBforPostgreSQL/servers' -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
Recommend 'PostgreSQL Server has > 10 firewall rules, some rules may not be needed';
$firewallRules = @($TargetObject.resources | Where-Object -FilterScript {
@ -18,7 +18,7 @@ Rule 'Azure.PostgreSQL.FirewallRuleCount' -Type 'Microsoft.DBforPostgreSQL/serve
}
# Synopsis: Determine if access from Azure services is required
Rule 'Azure.PostgreSQL.AllowAzureAccess' -Type 'Microsoft.DBforPostgreSQL/servers' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.PostgreSQL.AllowAzureAccess' -Type 'Microsoft.DBforPostgreSQL/servers' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$firewallRules = @($TargetObject.resources | Where-Object -FilterScript {
$_.Type -eq 'Microsoft.DBforPostgreSQL/servers/firewallRules' -and
(
@ -30,7 +30,7 @@ Rule 'Azure.PostgreSQL.AllowAzureAccess' -Type 'Microsoft.DBforPostgreSQL/server
}
# Synopsis: Determine if there is an excessive number of permitted IP addresses
Rule 'Azure.PostgreSQL.FirewallIPRange' -Type 'Microsoft.DBforPostgreSQL/servers' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.PostgreSQL.FirewallIPRange' -Type 'Microsoft.DBforPostgreSQL/servers' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$summary = GetIPAddressSummary
$summary.Public -le 10;
}

Просмотреть файл

@ -3,7 +3,7 @@
#
# Synopsis: Public IP addresses should be attached or cleaned up if not in use
Rule 'Azure.PublicIP.IsAttached' -Type 'Microsoft.Network/publicIPAddresses' -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.PublicIP.IsAttached' -Type 'Microsoft.Network/publicIPAddresses' -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
Recommend 'Public IP address should be attached'
($Null -ne $TargetObject.Properties.ipConfiguration) -and

Просмотреть файл

@ -3,11 +3,11 @@
#
# Synopsis: Redis Cache should only accept secure connections
Rule 'Azure.Redis.NonSslPort' -Type 'Microsoft.Cache/Redis' -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.Redis.NonSslPort' -Type 'Microsoft.Cache/Redis' -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
$TargetObject.properties.enableNonSslPort -eq $False
}
# Synopsis: Redis Cache should reject TLS versions older then 1.2
Rule 'Azure.Redis.MinTLS' -Type 'Microsoft.Cache/Redis' -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.Redis.MinTLS' -Type 'Microsoft.Cache/Redis' -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
$TargetObject.properties.minimumTlsVersion -eq '1.2'
}

Просмотреть файл

@ -7,7 +7,7 @@ if ($Null -eq $Configuration.azureAllowedRegions) {
}
# Synopsis: Resources should be tagged
Rule 'Azure.Resource.UseTags' -If { (SupportsTags) } -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.Resource.UseTags' -If { (SupportsTags) } -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
Reason $LocalizedData.ResourceNotTagged
# List of resource that support tags can be found here: https://docs.microsoft.com/en-us/azure/azure-resource-manager/tag-support
(Exists 'Tags') -and
@ -15,6 +15,6 @@ Rule 'Azure.Resource.UseTags' -If { (SupportsTags) } -Tag @{ severity = 'Awarene
}
# Synopsis: Resources should be deployed to allowed regions
Rule 'Azure.Resource.AllowedRegions' -If { ($Null -ne $Configuration.azureAllowedRegions) -and (SupportsRegions) } -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.Resource.AllowedRegions' -If { ($Null -ne $Configuration.azureAllowedRegions) -and (SupportsRegions) } -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
IsAllowedRegion
}

Просмотреть файл

@ -5,7 +5,7 @@
#region SQL Database
# Synopsis: Determine if there is an excessive number of firewall rules
Rule 'Azure.SQL.FirewallRuleCount' -Type 'Microsoft.Sql/servers' -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.SQL.FirewallRuleCount' -Type 'Microsoft.Sql/servers' -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
Recommend 'SQL Server has > 10 firewall rules, some rules may not be needed';
$firewallRules = @($TargetObject.resources | Where-Object -FilterScript {
@ -15,7 +15,7 @@ Rule 'Azure.SQL.FirewallRuleCount' -Type 'Microsoft.Sql/servers' -Tag @{ severit
}
# Synopsis: Determine if access from Azure services is required
Rule 'Azure.SQL.AllowAzureAccess' -Type 'Microsoft.Sql/servers' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.SQL.AllowAzureAccess' -Type 'Microsoft.Sql/servers' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$firewallRules = @($TargetObject.resources | Where-Object -FilterScript {
$_.Type -eq 'Microsoft.Sql/servers/firewallRules' -and
(
@ -27,13 +27,13 @@ Rule 'Azure.SQL.AllowAzureAccess' -Type 'Microsoft.Sql/servers' -Tag @{ severity
}
# Synopsis: Determine if there is an excessive number of permitted IP addresses
Rule 'Azure.SQL.FirewallIPRange' -Type 'Microsoft.Sql/servers' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.SQL.FirewallIPRange' -Type 'Microsoft.Sql/servers' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$summary = GetIPAddressSummary
$summary.Public -le 10;
}
# Synopsis: Enable threat detection for Azure SQL logical server
Rule 'Azure.SQL.ThreatDetection' -Type 'Microsoft.Sql/servers' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.SQL.ThreatDetection' -Type 'Microsoft.Sql/servers' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$policy = $TargetObject.resources | Where-Object -FilterScript {
$_.Type -eq 'Microsoft.Sql/servers/securityAlertPolicies'
}
@ -41,7 +41,7 @@ Rule 'Azure.SQL.ThreatDetection' -Type 'Microsoft.Sql/servers' -Tag @{ severity
}
# Synopsis: Enable auditing for Azure SQL logical server
Rule 'Azure.SQL.Auditing' -Type 'Microsoft.Sql/servers' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.SQL.Auditing' -Type 'Microsoft.Sql/servers' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$policy = $TargetObject.resources | Where-Object -FilterScript {
$_.Type -eq 'Microsoft.Sql/servers/auditingSettings'
}

Просмотреть файл

@ -3,23 +3,23 @@
#
# Synopsis: Storage accounts not using GRS may be at risk
Rule 'Azure.Storage.UseReplication' -Type 'Microsoft.Storage/storageAccounts' -Tag @{ severity = 'Single point of failure'; category = 'Reliability' } {
Rule 'Azure.Storage.UseReplication' -Type 'Microsoft.Storage/storageAccounts' -Tag @{ release = 'GA'; severity = 'Single point of failure'; category = 'Reliability' } {
Within 'sku.name' 'Standard_GRS', 'Standard_RAGRS'
}
# Synopsis: Storage accounts should only accept secure traffic
Rule 'Azure.Storage.SecureTransferRequired' -Type 'Microsoft.Storage/storageAccounts' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.Storage.SecureTransferRequired' -Type 'Microsoft.Storage/storageAccounts' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
$TargetObject.Properties.supportsHttpsTrafficOnly -eq $True
}
# Synopsis: Storage Service Encryption (SSE) should be enabled
Rule 'Azure.Storage.UseEncryption' -Type 'Microsoft.Storage/storageAccounts' -Tag @{ severity = 'Important'; category = 'Security configuration' } {
Rule 'Azure.Storage.UseEncryption' -Type 'Microsoft.Storage/storageAccounts' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security configuration' } {
Within 'Properties.encryption.services.blob.enabled' $True
Within 'Properties.encryption.services.file.enabled' $True
}
# Synopsis: Enable soft delete on Storage Accounts
Rule 'Azure.Storage.SoftDelete' -Type 'Microsoft.Storage/storageAccounts' -Tag @{ severity = 'Important'; category = 'Data recovery' } {
Rule 'Azure.Storage.SoftDelete' -Type 'Microsoft.Storage/storageAccounts' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Data recovery' } {
$serviceProperties = $TargetObject.resources | Where-Object -FilterScript {
$_.ResourceType -eq 'Microsoft.Storage/storageAccounts/blobServices'
}

Просмотреть файл

@ -2,8 +2,10 @@
# Validation rules for Azure subscriptions
#
#region RBAC
# Synopsis: Use groups for assigning permissions instead of individual user accounts
Rule 'Azure.Subscription.UseGroups' -Type 'Microsoft.Subscription' {
Rule 'Azure.RBAC.UseGroups' -Type 'Microsoft.Subscription' -Tag @{ release = 'GA' } {
$userAssignments = @($TargetObject.resources | Where-Object {
$_.ResourceType -eq 'Microsoft.Authorization/roleAssignments' -and
$_.ObjectType -eq 'User'
@ -12,7 +14,7 @@ Rule 'Azure.Subscription.UseGroups' -Type 'Microsoft.Subscription' {
}
# Synopsis: Limit the number of subscription Owners
Rule 'Azure.Subscription.LimitOwner' -Type 'Microsoft.Subscription' {
Rule 'Azure.RBAC.LimitOwner' -Type 'Microsoft.Subscription' -Tag @{ release = 'GA' } {
$assignments = @($TargetObject.resources | Where-Object {
$_.ResourceType -eq 'Microsoft.Authorization/roleAssignments' -and
$_.RoleDefinitionName -eq 'Owner' -and
@ -23,7 +25,7 @@ Rule 'Azure.Subscription.LimitOwner' -Type 'Microsoft.Subscription' {
}
# Synopsis: Limit RBAC inheritance from Management Groups
Rule 'Azure.Subscription.LimitMGDelegation' -Type 'Microsoft.Subscription' {
Rule 'Azure.RBAC.LimitMGDelegation' -Type 'Microsoft.Subscription' -Tag @{ release = 'GA' } {
$assignments = @($TargetObject.resources | Where-Object {
$_.ResourceType -eq 'Microsoft.Authorization/roleAssignments' -and
($_.Scope -like "/providers/Microsoft.Management/managementGroups/*")
@ -31,8 +33,30 @@ Rule 'Azure.Subscription.LimitMGDelegation' -Type 'Microsoft.Subscription' {
$assignments.Length -le 3
}
# Synopsis: Avoid using classic co-administrator roles
Rule 'Azure.RBAC.CoAdministrator' -Type 'Microsoft.Subscription' -Tag @{ release = 'GA' } {
$assignments = @($TargetObject.resources | Where-Object {
$_.ResourceType -eq 'Microsoft.Authorization/roleAssignments' -and
$_.RoleDefinitionName -eq 'CoAdministrator'
})
$assignments.Length -eq 0
}
# Synopsis: Use RBAC assignments on resource groups instead of individual resources
Rule 'Azure.RBAC.UseRGDelegation' -Type 'Microsoft.Resources/resourceGroups' -Tag @{ release = 'GA' } {
$assignments = @($TargetObject.resources | Where-Object {
$_.ResourceType -eq 'Microsoft.Authorization/roleAssignments' -and
$_.Scope -like "/subscriptions/*/resourceGroups/*/providers/*"
})
$assignments.Length -eq 0
}
#endregion RBAC
#region Security Center
# Synopsis: Security Center email and phone contact details should be set
Rule 'Azure.Subscription.SecurityCenterContact' -Type 'Microsoft.Subscription' -Tag @{ severity = 'Important'; category = 'Security operations' } {
Rule 'Azure.SecurityCenter.Contact' -Type 'Microsoft.Subscription' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security operations' } {
$contacts = $TargetObject.resources | Where-Object { $_.ResourceType -eq 'Microsoft.Security/securityContacts' };
$Null -ne $contacts;
foreach ($c in $contacts) {
@ -42,8 +66,8 @@ Rule 'Azure.Subscription.SecurityCenterContact' -Type 'Microsoft.Subscription' -
# TODO: Check Security Center recommendations
# Synopsis: Enable auto-provisioning on VMs to improve Security Center insights
Rule 'Azure.Subscription.SecurityCenterProvisioning' -Type 'Microsoft.Subscription' -Tag @{ severity = 'Important'; category = 'Security operations' } {
# Synopsis: Enable auto-provisioning on VMs to improve Azure Security Center insights
Rule 'Azure.SecurityCenter.Provisioning' -Type 'Microsoft.Subscription' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Security operations' } {
$provisioning = $TargetObject.resources | Where-Object { $_.ResourceType -eq 'Microsoft.Security/autoProvisioningSettings' };
$Null -ne $provisioning;
foreach ($s in $provisioning) {
@ -51,14 +75,7 @@ Rule 'Azure.Subscription.SecurityCenterProvisioning' -Type 'Microsoft.Subscripti
}
}
# Synopsis: Use RBAC assignments on resource groups instead of individual resources
Rule 'Azure.Subscription.UseRGDelegation' -Type 'Microsoft.Resources/resourceGroups' {
$assignments = @($TargetObject.resources | Where-Object {
$_.ResourceType -eq 'Microsoft.Authorization/roleAssignments' -and
$_.Scope -like "/subscriptions/*/resourceGroups/*/providers/*"
})
$assignments.Length -eq 0
}
#endregion Security Center
# TODO: Use policy
# TODO: Use resource locks

Просмотреть файл

@ -3,7 +3,7 @@
#
# Synopsis: Virtual machines should use managed disks
Rule 'Azure.VM.UseManagedDisks' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ severity = 'Single point of failure'; category = 'Reliability' } {
Rule 'Azure.VM.UseManagedDisks' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ release = 'GA'; severity = 'Single point of failure'; category = 'Reliability' } {
# Check OS disk
$Null -ne $TargetObject.properties.storageProfile.osDisk.managedDisk.id
@ -15,7 +15,7 @@ Rule 'Azure.VM.UseManagedDisks' -Type 'Microsoft.Compute/virtualMachines' -Tag @
}
# Synopsis: VMs must use premium disks or use availability sets/ zones to meet SLA requirements
Rule 'Azure.VM.Standalone' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ severity = 'Single point of failure'; category = 'Reliability' } {
Rule 'Azure.VM.Standalone' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ release = 'GA'; severity = 'Single point of failure'; category = 'Reliability' } {
Recommend 'Virtual machines should use availability sets or only premium disks'
$types = @(
@ -34,17 +34,17 @@ Rule 'Azure.VM.Standalone' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ sev
}
# Synopsis: VMs should not use expired promo SKU
Rule 'Azure.VM.PromoSku' -If { (IsVMPromoSku) } {
Rule 'Azure.VM.PromoSku' -If { (IsVMPromoSku) } -Tag @{ release = 'GA' } {
Match 'Properties.hardwareProfile.vmSize' -Not -Expression 'Standard_DS{0,1}1{0,1}[1-9]{1}_v2_Promo'
}
# Synopsis: VMs should not use Basic SKU
Rule 'Azure.VM.BasicSku' -Type 'Microsoft.Compute/virtualMachines' {
Rule 'Azure.VM.BasicSku' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ release = 'GA' } {
Match 'Properties.hardwareProfile.vmSize' -Not -Expression 'Basic_A[0-4]'
}
# Synopsis: Check disk caching is configured correctly for the workload
Rule 'Azure.VM.DiskCaching' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ severity = 'Important'; category = 'Performance' } {
Rule 'Azure.VM.DiskCaching' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Performance' } {
# Check OS disk
Within 'properties.storageProfile.osDisk.caching' 'ReadWrite'
@ -62,12 +62,12 @@ Rule 'Azure.VM.DiskCaching' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ se
}
# Synopsis: Network interfaces should inherit from virtual network
Rule 'Azure.VM.UniqueDns' -Type 'Microsoft.Network/networkInterfaces' -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.VM.UniqueDns' -Type 'Microsoft.Network/networkInterfaces' -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
$Assert.NullOrEmpty($TargetObject, 'Properties.dnsSettings.dnsServers')
}
# Synopsis: Managed disks should be attached to virtual machines
Rule 'Azure.VM.DiskAttached' -Type 'Microsoft.Compute/disks' -If { ($TargetObject.ResourceName -notlike '*-ASRReplica') } -Tag @{ severity = 'Awareness'; category = 'Operations management' } {
Rule 'Azure.VM.DiskAttached' -Type 'Microsoft.Compute/disks' -If { ($TargetObject.ResourceName -notlike '*-ASRReplica') } -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Operations management' } {
# Disks should be attached unless they are used by ASR, which are not attached until fail over
# Disks for VMs that are off are marked as Reserved
Within 'properties.diskState' 'Attached', 'Reserved'
@ -76,7 +76,7 @@ Rule 'Azure.VM.DiskAttached' -Type 'Microsoft.Compute/disks' -If { ($TargetObjec
# TODO: Check IOPS
# Synopsis: Managed disk is smaller than SKU size
Rule 'Azure.VM.DiskSizeAlignment' -Type 'Microsoft.Compute/disks' -Tag @{ severity = 'Awareness'; category = 'Cost management' } {
Rule 'Azure.VM.DiskSizeAlignment' -Type 'Microsoft.Compute/disks' -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Cost management' } {
$diskSize = @(32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)
$actualSize = $TargetObject.properties.diskSizeGB
@ -93,12 +93,12 @@ Rule 'Azure.VM.DiskSizeAlignment' -Type 'Microsoft.Compute/disks' -Tag @{ severi
# TODO: Check number of disks
# Synopsis: Use Hybrid Use Benefit
Rule 'Azure.VM.UseHybridUseBenefit' -If { (IsWindowsOS) } -Tag @{ severity = 'Awareness'; category = 'Cost management' } {
Rule 'Azure.VM.UseHybridUseBenefit' -If { (IsWindowsOS) } -Tag @{ release = 'GA'; severity = 'Awareness'; category = 'Cost management' } {
Within 'properties.licenseType' 'Windows_Server'
}
# Synopsis: Enabled accelerated networking for supported operating systems
Rule 'Azure.VM.AcceleratedNetworking' -If { (SupportsAcceleratedNetworking) } -Tag @{ severity = 'Important'; category = 'Performance optimisation' } {
Rule 'Azure.VM.AcceleratedNetworking' -If { (SupportsAcceleratedNetworking) } -Tag @{ release = 'GA'; severity = 'Important'; category = 'Performance optimisation' } {
$networkInterfaces = $TargetObject.resources | Where-Object { $_.ResourceType -eq 'Microsoft.Network/networkInterfaces' };
foreach ($interface in $networkInterfaces) {
($interface.Properties.enableAcceleratedNetworking -eq $True)
@ -106,33 +106,33 @@ Rule 'Azure.VM.AcceleratedNetworking' -If { (SupportsAcceleratedNetworking) } -T
}
# Synopsis: Availability sets should be aligned
Rule 'Azure.VM.ASAlignment' -Type 'Microsoft.Compute/availabilitySets' -Tag @{ severity = 'Single point of failure'; category = 'Reliability' } {
Rule 'Azure.VM.ASAlignment' -Type 'Microsoft.Compute/availabilitySets' -Tag @{ release = 'GA'; severity = 'Single point of failure'; category = 'Reliability' } {
Within 'sku.name' 'aligned'
}
# Synopsis: Availability sets should be deployed with at least two members
Rule 'Azure.VM.ASMinMembers' -Type 'Microsoft.Compute/availabilitySets' -Tag @{ severity = 'Single point of failure'; category = 'Reliability' } {
Rule 'Azure.VM.ASMinMembers' -Type 'Microsoft.Compute/availabilitySets' -Tag @{ release = 'GA'; severity = 'Single point of failure'; category = 'Reliability' } {
($TargetObject.properties.virtualmachines.id | Measure-Object).Count -ge 2
}
# Synopsis: Use Azure Disk Encryption
Rule 'Azure.VM.ADE' -Type 'Microsoft.Compute/disks' {
Rule 'Azure.VM.ADE' -Type 'Microsoft.Compute/disks' -Tag @{ release = 'GA' } {
$Assert.HasFieldValue($TargetObject, 'Properties.encryptionSettingsCollection.enabled', $True)
$Assert.HasFieldValue($TargetObject, 'Properties.encryptionSettingsCollection.encryptionSettings')
}
# Synopsis: Linux VMs should use public key pair
Rule 'Azure.VM.PublicKey' -If { (IsLinuxOS) } {
Rule 'Azure.VM.PublicKey' -If { (IsLinuxOS) } -Tag @{ release = 'GA' } {
$Assert.HasFieldValue($TargetObject, 'Properties.osProfile.linuxConfiguration.disablePasswordAuthentication', $True)
}
# Synopsis: Ensure that the VM agent is provisioned automatically
Rule 'Azure.VM.Agent' -Type 'Microsoft.Compute/virtualMachines' {
Rule 'Azure.VM.Agent' -Type 'Microsoft.Compute/virtualMachines' -Tag @{ release = 'GA' } {
$Assert.HasDefaultValue($TargetObject, 'Properties.osProfile.linuxConfiguration.provisionVMAgent', $True)
$Assert.HasDefaultValue($TargetObject, 'Properties.osProfile.windowsConfiguration.provisionVMAgent', $True)
}
# Synopsis: Ensure automatic updates are enabled at deployment
Rule 'Azure.VM.Updates' -Type 'Microsoft.Compute/virtualMachines' -If { (IsWindowsOS) } {
Rule 'Azure.VM.Updates' -Type 'Microsoft.Compute/virtualMachines' -If { (IsWindowsOS) } -Tag @{ release = 'GA' } {
$Assert.HasDefaultValue($TargetObject, 'Properties.osProfile.windowsConfiguration.enableAutomaticUpdates', $True)
}

Просмотреть файл

@ -5,7 +5,7 @@
#region Virtual Network
# Synopsis: Subnets should have NSGs assigned, except for the GatewaySubnet
Rule 'Azure.VirtualNetwork.UseNSGs' -Type 'Microsoft.Network/virtualNetworks' -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.VirtualNetwork.UseNSGs' -Type 'Microsoft.Network/virtualNetworks' -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
Recommend 'Subnets should have NSGs assigned'
# Get subnets
@ -22,7 +22,7 @@ Rule 'Azure.VirtualNetwork.UseNSGs' -Type 'Microsoft.Network/virtualNetworks' -T
# TODO: Check that NSG on GatewaySubnet is not defined
# Synopsis: VNETs should have at least two DNS servers assigned
Rule 'Azure.VirtualNetwork.SingleDNS' -Type 'Microsoft.Network/virtualNetworks' -Tag @{ severity = 'Single point of failure'; category = 'Reliability' } {
Rule 'Azure.VirtualNetwork.SingleDNS' -Type 'Microsoft.Network/virtualNetworks' -Tag @{ release = 'GA'; severity = 'Single point of failure'; category = 'Reliability' } {
# If DNS servers are customized, at least two IP addresses should be defined
if ($Assert.NullOrEmpty($TargetObject, 'properties.dhcpOptions.dnsServers').Result) {
$True;
@ -33,7 +33,7 @@ Rule 'Azure.VirtualNetwork.SingleDNS' -Type 'Microsoft.Network/virtualNetworks'
}
# Synopsis: VNETs should use Azure local DNS servers
Rule 'Azure.VirtualNetwork.LocalDNS' -Type 'Microsoft.Network/virtualNetworks' {
Rule 'Azure.VirtualNetwork.LocalDNS' -Type 'Microsoft.Network/virtualNetworks' -Tag @{ release = 'GA' } {
# If DNS servers are customized, check what range the IPs are in
if ($Assert.NullOrEmpty($TargetObject, 'properties.dhcpOptions.dnsServers').Result) {
$True;
@ -54,7 +54,7 @@ Rule 'Azure.VirtualNetwork.LocalDNS' -Type 'Microsoft.Network/virtualNetworks' {
}
# Synopsis: VNET peers should be connected
Rule 'Azure.VirtualNetwork.PeerState' -If { (HasPeerNetwork) } {
Rule 'Azure.VirtualNetwork.PeerState' -If { (HasPeerNetwork) } -Tag @{ release = 'GA' } {
$peers = @($TargetObject.Properties.virtualNetworkPeerings);
foreach ($peer in $peers) {
$peer | Within 'Properties.peeringState' 'Connected'
@ -66,7 +66,7 @@ Rule 'Azure.VirtualNetwork.PeerState' -If { (HasPeerNetwork) } {
#region Network Security Group
# Synopsis: Network security groups should avoid any inbound rules
Rule 'Azure.VirtualNetwork.NSGAnyInboundSource' -Type 'Microsoft.Network/networkSecurityGroups' -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.VirtualNetwork.NSGAnyInboundSource' -Type 'Microsoft.Network/networkSecurityGroups' -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
$inboundRules = @(GetOrderedNSGRules -Direction Inbound);
$rules = $inboundRules | Where-Object {
$_.properties.access -eq 'Allow' -and
@ -76,7 +76,7 @@ Rule 'Azure.VirtualNetwork.NSGAnyInboundSource' -Type 'Microsoft.Network/network
}
# Synopsis: Avoid blocking all inbound network traffic
Rule 'Azure.VirtualNetwork.NSGDenyAllInbound' -Type 'Microsoft.Network/networkSecurityGroups' {
Rule 'Azure.VirtualNetwork.NSGDenyAllInbound' -Type 'Microsoft.Network/networkSecurityGroups' -Tag @{ release = 'GA' } {
$inboundRules = @(GetOrderedNSGRules -Direction Inbound);
$denyRules = @($inboundRules | Where-Object {
$_.properties.access -eq 'Deny' -and
@ -86,7 +86,7 @@ Rule 'Azure.VirtualNetwork.NSGDenyAllInbound' -Type 'Microsoft.Network/networkSe
}
# Synopsis: Lateral traversal from application servers should be blocked
Rule 'Azure.VirtualNetwork.LateralTraversal' -Type 'Microsoft.Network/networkSecurityGroups' {
Rule 'Azure.VirtualNetwork.LateralTraversal' -Type 'Microsoft.Network/networkSecurityGroups' -Tag @{ release = 'GA' } {
$outboundRules = @(GetOrderedNSGRules -Direction Outbound);
$rules = @($outboundRules | Where-Object {
$_.properties.access -eq 'Deny' -and
@ -101,7 +101,7 @@ Rule 'Azure.VirtualNetwork.LateralTraversal' -Type 'Microsoft.Network/networkSec
}
# Synopsis: Network security groups should be associated to either a subnet or network interface
Rule 'Azure.VirtualNetwork.NSGAssociated' -Type 'Microsoft.Network/networkSecurityGroups' -If { IsExport } {
Rule 'Azure.VirtualNetwork.NSGAssociated' -Type 'Microsoft.Network/networkSecurityGroups' -If { IsExport } -Tag @{ release = 'GA' } {
$subnets = ($TargetObject.Properties.subnets | Measure-Object).Count;
$interfaces = ($TargetObject.Properties.networkInterfaces | Measure-Object).Count;
@ -114,7 +114,7 @@ Rule 'Azure.VirtualNetwork.NSGAssociated' -Type 'Microsoft.Network/networkSecuri
#region Application Gateway
# Synopsis: Application Gateway should use a minimum of two instances
Rule 'Azure.VirtualNetwork.AppGwMinInstance' -Type 'Microsoft.Network/applicationGateways' -Tag @{ severity = 'Important'; category = 'Reliability' } {
Rule 'Azure.VirtualNetwork.AppGwMinInstance' -Type 'Microsoft.Network/applicationGateways' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Reliability' } {
AnyOf {
# Applies to v1 and v2 without autoscale
$TargetObject.Properties.sku.capacity -ge 2
@ -125,17 +125,17 @@ Rule 'Azure.VirtualNetwork.AppGwMinInstance' -Type 'Microsoft.Network/applicatio
}
# Synopsis: Application Gateway should use a minimum of Medium
Rule 'Azure.VirtualNetwork.AppGwMinSku' -Type 'Microsoft.Network/applicationGateways' -Tag @{ severity = 'Important'; category = 'Performance' } {
Rule 'Azure.VirtualNetwork.AppGwMinSku' -Type 'Microsoft.Network/applicationGateways' -Tag @{ release = 'GA'; severity = 'Important'; category = 'Performance' } {
Within 'Properties.sku.name' 'WAF_Medium', 'Standard_Medium', 'WAF_Large', 'Standard_Large', 'WAF_v2', 'Standard_v2'
}
# Synopsis: Internet accessible Application Gateways should use WAF
Rule 'Azure.VirtualNetwork.AppGwUseWAF' -If { (IsAppGwPublic) } -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.VirtualNetwork.AppGwUseWAF' -If { (IsAppGwPublic) } -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
Within 'Properties.sku.tier' 'WAF', 'WAF_v2'
}
# Synopsis: Application Gateway should only accept a minimum of TLS 1.2
Rule 'Azure.VirtualNetwork.AppGwSSLPolicy' -Type 'Microsoft.Network/applicationGateways' -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.VirtualNetwork.AppGwSSLPolicy' -Type 'Microsoft.Network/applicationGateways' -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
Exists 'Properties.sslPolicy'
AnyOf {
Within 'Properties.sslPolicy.policyName' 'AppGwSslPolicy20170401S'
@ -144,23 +144,23 @@ Rule 'Azure.VirtualNetwork.AppGwSSLPolicy' -Type 'Microsoft.Network/applicationG
}
# Synopsis: Internet exposed Application Gateways should use prevention mode to protect backend resources
Rule 'Azure.VirtualNetwork.AppGwPrevention' -If { (IsAppGwPublic) } -Tag @{ severity = 'Critical'; category = 'Security configuration' } {
Rule 'Azure.VirtualNetwork.AppGwPrevention' -If { (IsAppGwPublic) } -Tag @{ release = 'GA'; severity = 'Critical'; category = 'Security configuration' } {
Within 'Properties.webApplicationFirewallConfiguration.firewallMode' 'Prevention'
}
# Synopsis: Application Gateway WAF must be enabled to protect backend resources
Rule 'Azure.VirtualNetwork.AppGwWAFEnabled' -If { (IsAppGwPublic) } {
Rule 'Azure.VirtualNetwork.AppGwWAFEnabled' -If { (IsAppGwPublic) } -Tag @{ release = 'GA' } {
Within 'Properties.webApplicationFirewallConfiguration.enabled' $True
}
# Synopsis: Application Gateway WAF should use OWASP 3.0 rules
Rule 'Azure.VirtualNetwork.AppGwOWASP' -If { (IsAppGwWAF) } {
Rule 'Azure.VirtualNetwork.AppGwOWASP' -If { (IsAppGwWAF) } -Tag @{ release = 'GA' } {
Within 'Properties.webApplicationFirewallConfiguration.ruleSetType' 'OWASP'
Within 'Properties.webApplicationFirewallConfiguration.ruleSetVersion' '3.0'
}
# Synopsis: Application Gateway WAF should not disable rules
Rule 'Azure.VirtualNetwork.AppGwWAFRules' -If { (IsAppGwWAF) } {
Rule 'Azure.VirtualNetwork.AppGwWAFRules' -If { (IsAppGwWAF) } -Tag @{ release = 'GA' } {
$disabledRules = @($TargetObject.Properties.webApplicationFirewallConfiguration.disabledRuleGroups)
$disabledRules.Count -eq 0
}
@ -170,7 +170,7 @@ Rule 'Azure.VirtualNetwork.AppGwWAFRules' -If { (IsAppGwWAF) } {
#region Network Interface
# Synopsis: Network interfaces should be attached
Rule 'Azure.VirtualNetwork.NICAttached' -Type 'Microsoft.Network/networkInterfaces' {
Rule 'Azure.VirtualNetwork.NICAttached' -Type 'Microsoft.Network/networkInterfaces' -Tag @{ release = 'GA' } {
Exists 'Properties.virtualMachine.id'
}
@ -179,7 +179,7 @@ Rule 'Azure.VirtualNetwork.NICAttached' -Type 'Microsoft.Network/networkInterfac
#region Load Balancer
# Synopsis: Use specific network probe
Rule 'Azure.VirtualNetwork.LBProbe' -Type 'Microsoft.Network/loadBalancers' {
Rule 'Azure.VirtualNetwork.LBProbe' -Type 'Microsoft.Network/loadBalancers' -Tag @{ release = 'GA' } {
$probes = $TargetObject.Properties.probes;
foreach ($probe in $probes) {
if ($probe.properties.port -in 80, 443, 8080) {

Просмотреть файл

@ -3,9 +3,39 @@
# Synopsis: Default baseline for Azure rules
kind: Baseline
metadata:
name: Azure.SubscriptionDefault
name: Azure.Default
spec:
binding:
targetType:
- ResourceType
- type
rule:
tag:
release: GA
---
# Synopsis: Includes Azure features in preview
kind: Baseline
metadata:
name: Azure.Preview
spec:
binding:
targetType:
- ResourceType
- type
rule:
tag:
release: [ 'GA', 'preview' ]
---
# Synopsis: Includes all Azure rules
kind: Baseline
metadata:
name: Azure.All
spec:
binding:
targetType:
- ResourceType
- type
rule:
tag: { }

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.ACR' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.ACR.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.ACR.AdminUser' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.ACR.AdminUser' };

Просмотреть файл

@ -20,11 +20,17 @@ $rootPath = $PWD;
Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Azure) -Force;
$here = (Resolve-Path $PSScriptRoot).Path;
Describe 'Azure.AKS' {
Describe 'Azure.AKS' -Tag AKS {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.AKS.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.AKS.MinNodeCount' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AKS.MinNodeCount' };
@ -58,6 +64,22 @@ Describe 'Azure.AKS' {
$ruleResult.TargetName | Should -Be 'cluster-A', 'cluster-C';
}
It 'Azure.AKS.PoolVersion' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AKS.PoolVersion' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'cluster-B';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -Be 'cluster-A', 'cluster-C';
}
It 'Azure.AKS.UseRBAC' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AKS.UseRBAC' };
@ -73,5 +95,98 @@ Describe 'Azure.AKS' {
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -Be 'cluster-A', 'cluster-C';
}
It 'Azure.AKS.PodSecurityPolicy' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AKS.PodSecurityPolicy' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'cluster-A', 'cluster-B';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'cluster-C';
}
It 'Azure.AKS.NetworkPolicy' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AKS.NetworkPolicy' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'cluster-A', 'cluster-B';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'cluster-C';
}
It 'Azure.AKS.PoolScaleSet' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AKS.PoolScaleSet' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'cluster-A', 'cluster-B';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'cluster-C';
}
}
Context 'With Template' {
$templatePath = Join-Path -Path $here -ChildPath 'Resources.AKS.Template.json';
$outputFile = Join-Path -Path $rootPath -ChildPath out/tests/Resources.AKS.json;
Export-AzTemplateRuleData -TemplateFile $templatePath -OutputPath $outputFile;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $outputFile -Outcome All;
It 'Azure.AKS.Version' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AKS.Version' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'clusterA/agentpool2';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'clusterA', 'clusterA/agentpool3';
}
It 'Azure.AKS.PoolScaleSet' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AKS.PoolScaleSet' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'clusterA/agentpool2';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'clusterA', 'clusterA/agentpool3';
}
}
}

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.AppService' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.AppService.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.AppService.PlanInstanceCount' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AppService.PlanInstanceCount' };

Просмотреть файл

@ -24,10 +24,31 @@ Describe 'Baselines' -Tag Baseline {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.Resource.json';
Context 'Binding' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -Outcome All -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath -Outcome All;
It 'TargetType' {
$result.TargetType | Should -Not -BeIn 'System.Management.Automation.PSCustomObject';
}
}
Context 'Rule' {
It 'With default baseline' {
$result = @(Get-PSRule -Module PSRule.Rules.Azure -Baseline 'Azure.Default' -WarningAction Ignore);
$filteredResult = @($result | Where-Object { $_.Tag.release -eq 'preview'});
$filteredResult | Should -BeNullOrEmpty;
}
It 'With Azure.Preview' {
$result = @(Get-PSRule -Module PSRule.Rules.Azure -Baseline 'Azure.Preview' -WarningAction Ignore);
$filteredResult = @($result | Where-Object { $_.Tag.release -in 'GA', 'preview'});
$filteredResult | Should -Not -BeNullOrEmpty;
$filteredResult.Length | Should -BeGreaterThan 70;
}
}
}

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.DataFactory' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.DataFactory.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.DataFactory.Version' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.DataFactory.Version' };

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.MySQL' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.MySQL.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.MySQL.UseSSL' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.MySQL.UseSSL' };

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.PostgreSQL' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.PostgreSQL.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.PostgreSQL.UseSSL' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.PostgreSQL.UseSSL' };

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.PublicIP' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.PublicIP.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.PublicIP.IsAttached' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.PublicIP.IsAttached' };

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.Redis' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.Redis.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.Redis.NonSslPort' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Redis.NonSslPort' };

Просмотреть файл

@ -24,8 +24,15 @@ Describe 'Azure.Resource' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.Resource.json';
Context 'Conditions' {
$options = New-PSRuleOption -BaselineConfiguration @{ 'azureAllowedRegions' = @('region-A') };
$result = Invoke-PSRule -Module PSRule.Rules.Azure -Option $options -Outcome All -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$option = New-PSRuleOption -BaselineConfiguration @{ 'azureAllowedRegions' = @('region-A') };
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
Option = $option
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath -Outcome All;
It 'Azure.Resource.UseTags' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Resource.UseTags' };
@ -71,8 +78,15 @@ Describe 'Azure.Resource' {
$parameterPath = Join-Path -Path $here -ChildPath 'Resources.Parameters.json';
$outputFile = Join-Path -Path $rootPath -ChildPath out/tests/Resources.Resource.json;
Export-AzTemplateRuleData -TemplateFile $templatePath -ParameterFile $parameterPath -OutputPath $outputFile;
$options = New-PSRuleOption -BaselineConfiguration @{ 'azureAllowedRegions' = @('region-A') };
$result = Invoke-PSRule -Module PSRule.Rules.Azure -Option $options -InputPath $outputFile -Outcome All -WarningAction Ignore -ErrorAction Stop;
$option = New-PSRuleOption -BaselineConfiguration @{ 'azureAllowedRegions' = @('region-A') };
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
Option = $option
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $outputFile -Outcome All;
It 'Azure.Resource.UseTags' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Resource.UseTags' };

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.SQL' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.SQL.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.SQL.FirewallRuleCount' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.SQL.FirewallRuleCount' };

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.Storage' -Tag Storage {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.Storage.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.Storage.UseReplication' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Storage.UseReplication' };

Просмотреть файл

@ -24,26 +24,32 @@ Describe 'Azure.Subscription' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.Subscription.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
It 'Azure.Subscription.UseGroups' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Subscription.UseGroups' };
It 'Azure.RBAC.UseGroups' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.RBAC.UseGroups' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'subscription-B';
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'subscription-B', 'subscription-C';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -BeIn 2;
$ruleResult.TargetName | Should -BeIn 'subscription-A', 'subscription-C';
$ruleResult.Length | Should -BeIn 1;
$ruleResult.TargetName | Should -BeIn 'subscription-A';
}
It 'Azure.Subscription.LimitOwner' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Subscription.LimitOwner' };
It 'Azure.RBAC.LimitOwner' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.RBAC.LimitOwner' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
@ -58,8 +64,8 @@ Describe 'Azure.Subscription' {
$ruleResult.TargetName | Should -BeIn 'subscription-A', 'subscription-C';
}
It 'Azure.Subscription.LimitMGDelegation' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Subscription.LimitMGDelegation' };
It 'Azure.RBAC.LimitMGDelegation' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.RBAC.LimitMGDelegation' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
@ -74,8 +80,24 @@ Describe 'Azure.Subscription' {
$ruleResult.TargetName | Should -BeIn 'subscription-B', 'subscription-A';
}
It 'Azure.Subscription.UseRGDelegation' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Subscription.UseRGDelegation' };
It 'Azure.RBAC.CoAdministrator' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.RBAC.CoAdministrator' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 1;
$ruleResult.TargetName | Should -Be 'subscription-C';
# Pass
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
$ruleResult | Should -Not -BeNullOrEmpty;
$ruleResult.Length | Should -Be 2;
$ruleResult.TargetName | Should -BeIn 'subscription-B', 'subscription-A';
}
It 'Azure.RBAC.UseRGDelegation' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.RBAC.UseRGDelegation' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
@ -90,8 +112,8 @@ Describe 'Azure.Subscription' {
$ruleResult.TargetName | Should -Be 'test-rg-A';
}
It 'Azure.Subscription.SecurityCenterContact' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Subscription.SecurityCenterContact' };
It 'Azure.SecurityCenter.Contact' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.SecurityCenter.Contact' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
@ -106,8 +128,8 @@ Describe 'Azure.Subscription' {
$ruleResult.TargetName | Should -Be 'subscription-C';
}
It 'Azure.Subscription.SecurityCenterProvisioning' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Subscription.SecurityCenterProvisioning' };
It 'Azure.SecurityCenter.Provisioning' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.SecurityCenter.Provisioning' };
# Fail
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.VirtualMachine' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.VirtualMachine.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -Outcome All -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath -Outcome All;
It 'Azure.VM.UseManagedDisks' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.VM.UseManagedDisks' };

Просмотреть файл

@ -24,7 +24,13 @@ Describe 'Azure.VirtualNetwork' -Tag 'Network' {
$dataPath = Join-Path -Path $here -ChildPath 'Resources.VirtualNetwork.json';
Context 'Conditions' {
$result = Invoke-PSRule -Module PSRule.Rules.Azure -InputPath $dataPath -Outcome All -WarningAction Ignore -ErrorAction Stop;
$invokeParams = @{
Baseline = 'Azure.All'
Module = 'PSRule.Rules.Azure'
WarningAction = 'Ignore'
ErrorAction = 'Stop'
}
$result = Invoke-PSRule @invokeParams -InputPath $dataPath -Outcome All;
It 'Azure.VirtualNetwork.UseNSGs' {
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.VirtualNetwork.UseNSGs' };

Просмотреть файл

@ -0,0 +1,120 @@
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"clusterName": {
"defaultValue": "clusterA",
"type": "string"
},
"clusterLocation": {
"defaultValue": "[resourceGroup().location]",
"type": "string"
},
"vnetId": {
"defaultValue": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/Microsoft.Network/virtualNetworks/vnetA",
"type": "string"
},
"workspaceId": {
"defaultValue": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test/providers/microsoft.operationalinsights/workspaces/workspaceA",
"type": "string"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.ContainerService/managedClusters",
"apiVersion": "2019-10-01",
"name": "[parameters('clusterName')]",
"location": "[parameters('clusterLocation')]",
"properties": {
"kubernetesVersion": "1.14.8",
"dnsPrefix": "[concat('npcorp-', parameters('clusterName'))]",
"agentPoolProfiles": [
{
"name": "agentpool1",
"count": 3,
"vmSize": "Standard_B2ms",
"osDiskSizeGB": 100,
"vnetSubnetID": "[concat(parameters('vnetId'), '/subnets/subnet-01')]",
"maxPods": 50,
"type": "VirtualMachineScaleSets",
"orchestratorVersion": "1.14.8",
"osType": "Linux"
}
],
"servicePrincipalProfile": {
"clientId": "00000000-0000-0000-0000-000000000000"
},
"addonProfiles": {
"aciConnectorLinux": {
"enabled": true,
"config": {
"SubnetName": "subnet-aci"
}
},
"azurepolicy": {
"enabled": true
},
"httpApplicationRouting": {
"enabled": true
},
"kubeDashboard": {
"enabled": false
},
"omsagent": {
"enabled": true,
"config": {
"logAnalyticsWorkspaceResourceID": "[parameters('workspaceId')]"
}
}
},
"enableRBAC": true,
"enablePodSecurityPolicy": true,
"networkProfile": {
"networkPlugin": "azure",
"networkPolicy": "azure",
"loadBalancerSku": "Basic",
"serviceCidr": "192.168.0.0/16",
"dnsServiceIP": "192.168.0.4",
"dockerBridgeCidr": "172.17.0.1/16"
}
}
},
{
"type": "Microsoft.ContainerService/managedClusters/agentPools",
"apiVersion": "2019-10-01",
"name": "[concat(parameters('clusterName'), '/agentpool2')]",
"dependsOn": [
"[resourceId('Microsoft.ContainerService/managedClusters', parameters('clusterName'))]"
],
"properties": {
"count": 3,
"vmSize": "Standard_B2ms",
"osDiskSizeGB": 100,
"vnetSubnetID": "[concat(parameters('vnetId'), '/subnets/subnet-02')]",
"maxPods": 30,
"type": "AvailabilitySet",
"orchestratorVersion": "1.11.5",
"osType": "Linux"
}
},
{
"type": "Microsoft.ContainerService/managedClusters/agentPools",
"apiVersion": "2019-10-01",
"name": "[concat(parameters('clusterName'), '/agentpool3')]",
"dependsOn": [
"[resourceId('Microsoft.ContainerService/managedClusters', parameters('clusterName'))]"
],
"properties": {
"count": 3,
"vmSize": "Standard_B2ms",
"osDiskSizeGB": 100,
"vnetSubnetID": "[concat(parameters('vnetId'), '/subnets/subnet-03')]",
"maxPods": 50,
"type": "VirtualMachineScaleSets",
"orchestratorVersion": "1.14.8",
"osType": "Linux"
}
}
]
}

Просмотреть файл

@ -177,6 +177,30 @@
"AlertsToAdmins": "On",
"ResourceType": "Microsoft.Security/securityContacts"
},
{
"RoleAssignmentId": null,
"Scope": "/subscriptions/00000000-0000-0000-0000-000000000000",
"DisplayName": "user1@contoso.com",
"SignInName": "user1@contoso.com",
"RoleDefinitionName": "ServiceAdministrator;AccountAdministrator",
"RoleDefinitionId": null,
"ObjectId": null,
"ObjectType": "User",
"CanDelegate": false,
"ResourceType": "Microsoft.Authorization/roleAssignments"
},
{
"RoleAssignmentId": null,
"Scope": "/subscriptions/00000000-0000-0000-0000-000000000000",
"DisplayName": "user2@contoso.com",
"SignInName": "user2@contoso.com",
"RoleDefinitionName": "CoAdministrator",
"RoleDefinitionId": null,
"ObjectId": null,
"ObjectType": "User",
"CanDelegate": false,
"ResourceType": "Microsoft.Authorization/roleAssignments"
},
{
"RoleAssignmentId": "/providers/Microsoft.Management/managementGroups/test-management-group/providers/Microsoft.Authorization/roleAssignments/00000000-0000-0000-0000-000000000000",
"Scope": "/providers/Microsoft.Management/managementGroups/test-management-group",

Просмотреть файл

@ -20,19 +20,30 @@ $rootPath = $PWD;
Import-Module (Join-Path -Path $rootPath -ChildPath out/modules/PSRule.Rules.Azure) -Force;
Describe 'Rule quality' {
Context 'Metadata' {
$result = Get-PSRule -Module PSRule.Rules.Azure -WarningAction Ignore;
$rules = Get-PSRule -Module PSRule.Rules.Azure -Baseline 'Azure.All' -WarningAction SilentlyContinue;
foreach ($rule in $result) {
Context 'Naming' {
foreach ($rule in $rules) {
It $rule.RuleName {
$rule.Description | Should -Not -BeNullOrEmpty;
$rule.Info.Annotations.severity | Should -Not -BeNullOrEmpty;
$rule.Info.Annotations.category | Should -Not -BeNullOrEmpty;
$rule.RuleName | Should -BeLike "Azure*";
# $rule.RuleName.Length -le 35 | Should -Be $True;
if ($rule.RuleName.Length -gt 35) {
Write-Warning -Message "Rule name $($rule.RuleName) is longer than 35 characters.";
}
}
}
}
Context 'Metadata' {
foreach ($rule in $rules) {
It $rule.RuleName {
$rule.Synopsis | Should -Not -BeNullOrEmpty;
$rule.Description | Should -Not -BeNullOrEmpty;
$rule.Tag.release | Should -BeIn 'GA', 'preview';
$rule.Info.Annotations.severity | Should -Not -BeNullOrEmpty;
$rule.Info.Annotations.category | Should -Not -BeNullOrEmpty;
$rule.Info.GetOnlineHelpUri() | Should -Not -BeNullOrEmpty;
}
}
}
}