Skip to content

Commit

Permalink
Replaced Azure_AllowedRegions #941 (#2429)
Browse files Browse the repository at this point in the history
* Replaced Azure_AllowedRegions #941

* Clean up
  • Loading branch information
BernieWhite authored Sep 11, 2023
1 parent 10edef7 commit 578a721
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 31 deletions.
12 changes: 12 additions & 0 deletions docs/CHANGELOG-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers
If you have this option configured, please update it to `AZURE_AKS_CLUSTER_MINIMUM_VERSION`.
Support for `Azure_AKSMinimumVersion` will be removed in v2.
See [upgrade notes][1] for more information.
- The configuration option `Azure_AllowedRegions` is replaced with `AZURE_RESOURCE_ALLOWED_LOCATIONS`.
If you have this option configured, please update it to `AZURE_RESOURCE_ALLOWED_LOCATIONS`.
Support for `Azure_AllowedRegions` will be removed in v2.
See [upgrade notes][1] for more information.
- The `SupportsTag` PowerShell function has been replaced with the `Azure.Resource.SupportsTags` selector.
Update PowerShell rules to use the `Azure.Resource.SupportsTags` selector instead.
Support for the `SupportsTag` function will be removed in v2.
Expand All @@ -26,6 +30,14 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers

What's changed since pre-release v1.30.0-B0047:

- General improvements:
- **Important change:** Replaced `Azure_AllowedRegions` option with `AZURE_RESOURCE_ALLOWED_LOCATIONS`. [#941](https://github.com/Azure/PSRule.Rules.Azure/issues/941)
- For compatibility, if `Azure_AllowedRegions` is set it will be used instead of `AZURE_RESOURCE_ALLOWED_LOCATIONS`.
- If only `AZURE_RESOURCE_ALLOWED_LOCATIONS` is set, this value will be used.
- The default will be used neither options are configured.
- If `Azure_AllowedRegions` is set a warning will be generated until the configuration is removed.
- Support for `Azure_AllowedRegions` is deprecated and will be removed in v2.
- See [upgrade notes][1] for details.
- Engineering:
- Bump Microsoft.NET.Test.Sdk to v17.7.2.
[#2407](https://github.com/Azure/PSRule.Rules.Azure/pull/2407)
Expand Down
2 changes: 1 addition & 1 deletion docs/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ New name | Old name
-------- | -------- | --------------
`AZURE_AKS_CLUSTER_MINIMUM_VERSION` | `Azure_AKSMinimumVersion` | :octicons-milestone-24: v1.12.0
`AZURE_AKS_POOL_MINIMUM_MAXPODS` | `Azure_AKSNodeMinimumMaxPods` | _TBA - not available_
`AZURE_RESOURCE_ALLOWED_LOCATIONS` | `Azure_AllowedRegions` | _TBA - not available_
`AZURE_RESOURCE_ALLOWED_LOCATIONS` | `Azure_AllowedRegions` | :octicons-milestone-24: v1.30.0
`AZURE_APIM_MINIMUM_CERTIFICATE_LIFETIME` | `Azure_MinimumCertificateLifetime` | _TBA - not available_

!!! Note
Expand Down
112 changes: 107 additions & 5 deletions docs/en/rules/Azure.Resource.AllowedRegions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
severity: Awareness
reviewed: 2023-09-10
severity: Important
pillar: Security
category: Design
resource: All resources
Expand All @@ -14,15 +15,116 @@ Resources should be deployed to allowed regions.

## DESCRIPTION

Resources should be deployed to allowed regions.
Azure supports deployment to many locations around the world called regions.
Many organizations have requirements that limit where data can be stored or processed.
This is commonly known as data residency.

Most Azure resources must be deployed to a specific region.
To align with your organizational requirements, you may choose to limit the regions that resources can be deployed to.

Some resources, particularly those related to preview services or features, may not be available in all regions.

## RECOMMENDATION

Resources should be deployed to allowed regions.
Consider deploying resources to allowed regions to align with your organizational requirements.
Also consider using Azure Policy to enforce allowed regions.

## EXAMPLES

### Configure with Azure template

To deploy resources that pass this rule:

- Set the `location` property to an allowed region. OR
- Instead of hard coding the location, use a parameter to allow the location to be specified at deployment time.

For example:

```json
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-01-01",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_GRS"
},
"kind": "StorageV2",
"properties": {
"allowBlobPublicAccess": false,
"supportsHttpsTrafficOnly": true,
"minimumTlsVersion": "TLS1_2",
"accessTier": "Hot",
"allowSharedKeyAccess": false,
"networkAcls": {
"defaultAction": "Deny"
}
}
}
```

### Configure with Bicep

To deploy resources that pass this rule:

- Set the `location` property to an allowed region. OR
- Instead of hard coding the location, use a parameter to allow the location to be specified at deployment time.

For example:

```bicep
@sys.description('The location resources will be deployed.')
param location string = resourceGroup().location
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: name
location: location
sku: {
name: 'Standard_GRS'
}
kind: 'StorageV2'
properties: {
allowBlobPublicAccess: false
supportsHttpsTrafficOnly: true
minimumTlsVersion: 'TLS1_2'
accessTier: 'Hot'
allowSharedKeyAccess: false
networkAcls: {
defaultAction: 'Deny'
}
}
}
```

## NOTES

This rule requires one or more allowed regions to be configured.
By default, all regions are allowed.
To configure this rule:

- Override the `Azure_AllowedRegions` configuration value to set the allowed regions for validation.
To configure this rule set the `AZURE_RESOURCE_ALLOWED_LOCATIONS` configuration value to a set of allowed regions.

For example:

```yaml
configuration:
AZURE_RESOURCE_ALLOWED_LOCATIONS:
- australiaeast
- australiasoutheast
```
If you configure this `AZURE_RESOURCE_ALLOWED_LOCATIONS` configuration value,
also consider setting `AZURE_RESOURCE_GROUP` the configuration value to when resources use the location of the resource group.

For example:

```yaml
configuration:
AZURE_RESOURCE_GROUP:
location: australiaeast
```

## LINKS

- [Regulatory compliance](https://learn.microsoft.com/azure/well-architected/security/design-regulatory-compliance)
- [Data residency in Azure](https://azure.microsoft.com/explore/global-infrastructure/data-residency/#overview)
- [Azure geographies](https://azure.microsoft.com/explore/global-infrastructure/geographies/#geographies)
28 changes: 21 additions & 7 deletions docs/setup/configuring-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,39 +322,53 @@ configuration:
AZURE_COSMOS_DEFENDER_PER_ACCOUNT: true
```

### Azure_AllowedRegions
### AZURE_RESOURCE_ALLOWED_LOCATIONS

:octicons-milestone-24: v1.30.0

> Applies to [Azure.Resource.AllowedRegions](../en/rules/Resource.AllowedRegions.md).

This configuration option specifies a list of allowed locations that resources can be deployed to.
Rules that check the location of Azure resources fail when a resource or resource group is created in a different region.

By default, `Azure_AllowedRegions` is not configured.
The rule `Azure.Resource.AllowedRegions` is skipped when no allowed locations are configured.
By default, `AZURE_RESOURCE_ALLOWED_LOCATIONS` is not configured.

Syntax:

```yaml
configuration:
Azure_AllowedRegions: array # An array of regions
AZURE_RESOURCE_ALLOWED_LOCATIONS: array # An array of regions
```

Default:

```yaml
# YAML: The default Azure_AllowedRegions configuration option
configuration:
Azure_AllowedRegions: []
AZURE_RESOURCE_ALLOWED_LOCATIONS: []
```

Example:

```yaml
# YAML: Set the Azure_AllowedRegions configuration option to Australia East, Australia South East
# YAML: Set the AZURE_RESOURCE_ALLOWED_LOCATIONS configuration option to Australia East, Australia South East
configuration:
Azure_AllowedRegions:
AZURE_RESOURCE_ALLOWED_LOCATIONS:
- australiaeast
- australiasoutheast
```

If you configure the `AZURE_RESOURCE_ALLOWED_LOCATIONS` configuration value,
also consider setting `AZURE_RESOURCE_GROUP` the configuration value to when resources use the location of the resource group.

For example:

```yaml
configuration:
AZURE_RESOURCE_GROUP:
location: australiaeast
```

### Azure_MinimumCertificateLifetime

This configuration option determines the minimum number of days allowed before certificate expiry.
Expand Down
3 changes: 2 additions & 1 deletion docs/upgrade-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ To locate any configurations, search for the old option names within your Infras
New name | Old name | Available from
-------- | -------- | --------------
`AZURE_AKS_CLUSTER_MINIMUM_VERSION` | `Azure_AKSMinimumVersion` | :octicons-milestone-24: v1.12.0
`AZURE_RESOURCE_ALLOWED_LOCATIONS` | `Azure_AllowedRegions` | :octicons-milestone-24: v1.30.0

To update your configuration, use the new name instead.

Expand All @@ -54,7 +55,7 @@ To update your configuration, use the new name instead.

```bash
# Bash: Set the AZURE_AKS_CLUSTER_MINIMUM_VERSION configuration option to 1.25.6
export PSRULE_CONFIGURATION_AZURE_AKS_CLUSTER_MINIMUM_VERSION=1.25.6
export PSRULE_CONFIGURATION_AZURE_AKS_CLUSTER_MINIMUM_VERSION="1.25.6"
```

=== "GitHub Actions"
Expand Down
4 changes: 2 additions & 2 deletions src/PSRule.Rules.Azure/Runtime/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static class Helper
/// <summary>
/// Create a singleton context for running within PSRule.
/// </summary>
public static IService CreateService(string minimum, int timeout)
public static IRuntimeService CreateService(string minimum, int timeout)
{
return new RuntimeService(minimum, timeout);
}
Expand Down Expand Up @@ -88,7 +88,7 @@ internal static bool UsesReferenceFunction(string expression)
}

/// <summary>
/// Checks if the value of the expresion is secure, whether by using secure parameters, references to KeyVault, or the ListKeys function.
/// Checks if the value of the expression is secure, whether by using secure parameters, references to KeyVault, or the ListKeys function.
/// </summary>
public static bool HasSecureValue(string expression, string[] secureParameters)
{
Expand Down
59 changes: 52 additions & 7 deletions src/PSRule.Rules.Azure/Runtime/RuntimeService.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,50 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Collections.Generic;
using PSRule.Rules.Azure.Data.Bicep;

namespace PSRule.Rules.Azure.Runtime
{
/// <summary>
/// A context when running within PSRule.
/// </summary>
public interface IRuntimeService : IService
{
/// <summary>
/// Configures the timeout for Bicep expansion.
/// </summary>
int Timeout { get; }

/// <summary>
/// The minimum version of Bicep.
/// </summary>
string Minimum { get; }

/// <summary>
/// Specified the allowed locations for the organization.
/// </summary>
/// <param name="locations">Configures the allowed list of locations.</param>
void WithAllowedLocations(string[] locations);

/// <summary>
/// Determines if the specified location is within the allowed set.
/// </summary>
/// <param name="location">The location to check.</param>
/// <returns>Returns <c>true</c> when the location is allowed. Otherwise <c>false</c> is returned.</returns>
bool IsAllowedLocation(string location);
}

/// <summary>
/// A singleton context when running is PSRule.
/// </summary>
internal sealed class RuntimeService : IService
internal sealed class RuntimeService : IRuntimeService
{
private const int BICEP_TIMEOUT_MIN = 1;
private const int BICEP_TIMEOUT_MAX = 120;

private bool _Disposed;
private HashSet<string> _AllowedLocations;

/// <summary>
/// Create a runtime service.
Expand All @@ -28,18 +59,32 @@ public RuntimeService(string minimum, int timeout)
Timeout = BICEP_TIMEOUT_MAX;
}

/// <summary>
/// Configures the timeout for Bicep expansion.
/// </summary>
/// <inheritdoc/>
public int Timeout { get; }

/// <summary>
/// The minimum version of Bicep.
/// </summary>
/// <inheritdoc/>
public string Minimum { get; }

/// <inheritdoc/>
public BicepHelper.BicepInfo Bicep { get; internal set; }

/// <inheritdoc/>
public void WithAllowedLocations(string[] locations)
{
if (locations == null || locations.Length == 0)
return;

_AllowedLocations = new HashSet<string>(locations, LocationHelper.Comparer);
}

/// <inheritdoc/>
public bool IsAllowedLocation(string location)
{
return location == null ||
_AllowedLocations == null ||
_AllowedLocations.Contains(location);
}

#region IDisposable

private void Dispose(bool disposing)
Expand Down
2 changes: 2 additions & 0 deletions src/PSRule.Rules.Azure/en/PSRule-rules.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@{
MinTLSVersion = "Minimum TLS version is set to {0}."
ResourceNotTagged = "The resource is not tagged."
LocationNotAllowed = "The location '{0}' is not in the allowed set of resource locations."
TcpHealthProbe = "The health probe ({0}) is using TCP."
RootHttpProbePath = "The health probe ({0}) is using '{1}'."
AKSVersion = "The Kubernetes version is v{0}."
Expand Down Expand Up @@ -62,6 +63,7 @@
PremiumRedisCacheAvailabilityZone = "The premium redis cache ({0}) deployed to region ({1}) should use a minimum of two availability zones from the following [{2}]."
EnterpriseRedisCacheAvailabilityZone = "The enterprise redis cache ({0}) deployed to region ({1}) should be zone-redundant."
AKSMinimumVersionReplace = "The configuration option 'Azure_AKSMinimumVersion' has been replaced with 'AZURE_AKS_CLUSTER_MINIMUM_VERSION'. The option 'Azure_AKSMinimumVersion' is deprecated and will no longer work in the next major version. Please update your configuration to the new name. See https://aka.ms/ps-rule-azure/upgrade."
AzureAllowedRegionsReplace = "The configuration option 'Azure_AllowedRegions' has been replaced with 'AZURE_RESOURCE_ALLOWED_LOCATIONS'. The option 'Azure_AllowedRegions' is deprecated and will no longer work in the next major version. Please update your configuration to the new name. See https://aka.ms/ps-rule-azure/upgrade."
# DeprecatedSupportsTags = "The 'SupportsTags' PowerShell function has been replaced with the selector 'Azure.Resource.SupportsTags'. The 'SupportsTags' function is deprecated and will no longer work in the next major version. Please update your PowerShell rules to the selector instead. See https://aka.ms/ps-rule-azure/upgrade."
KeyVaultAutoRotationPolicy = "The key ({0}) should enable a auto-rotation policy."
ReplicaNotFound = "A replica was not found."
Expand Down
12 changes: 5 additions & 7 deletions src/PSRule.Rules.Azure/rules/Azure.Resource.Rule.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ Rule 'Azure.Resource.UseTags' -Ref 'AZR-000166' -With 'Azure.Resource.SupportsTa
$Assert.Create(($TargetObject.Tags.PSObject.Members | Where-Object { $_.MemberType -eq 'NoteProperty' }) -ne $Null)
}

# Synopsis:Resources should be deployed to allowed regions.
Rule 'Azure.Resource.AllowedRegions' -Ref 'AZR-000167' -If { ($Null -ne $Configuration.Azure_AllowedRegions) -and ($Configuration.Azure_AllowedRegions.Length -gt 0) -and (SupportsRegions) -and $PSRule.TargetType -ne 'Microsoft.Resources/deployments' } -Tag @{ release = 'GA'; ruleSet = '2020_06' } {
$region = @($Configuration.Azure_AllowedRegions);
foreach ($r in $Configuration.Azure_AllowedRegions) {
$region += ($r -replace ' ', '')
}
$Assert.In($TargetObject, 'location', $region);
# Synopsis: Resources should be deployed to allowed regions.
Rule 'Azure.Resource.AllowedRegions' -Ref 'AZR-000167' -If { (SupportsRegions) -and $PSRule.TargetType -ne 'Microsoft.Resources/deployments' -and $Assert.HasFieldValue($TargetObject, 'location').Result } -Tag @{ release = 'GA'; ruleSet = '2020_06' } {
$context = $PSRule.GetService('Azure.Context');
$location = $TargetObject.location;
$Assert.Create($context.IsAllowedLocation($location), $LocalizedData.LocationNotAllowed, $location);
}

# Synopsis: Use Resource Group naming requirements
Expand Down
Loading

0 comments on commit 578a721

Please sign in to comment.