Add additional AKS rules and fixes (#192)
This commit is contained in:
Родитель
b6eebdbd94
Коммит
be63f9d135
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче