From 1bf98e1e51b8a4c230cf4910e49f9de0fba2bf12 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 17:21:54 +0000 Subject: [PATCH 1/9] Initial plan From 9fb095f66d7ad93afd32861993d4cba733118dc6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 17:30:03 +0000 Subject: [PATCH 2/9] Add Azure.Redis.Retirement rule Co-authored-by: BenjaminEngeset <99641908+BenjaminEngeset@users.noreply.github.com> --- docs/changelog.md | 3 + docs/en/rules/Azure.Redis.Retirement.md | 105 ++++++++++++++++++ src/PSRule.Rules.Azure/en/PSRule-rules.psd1 | 1 + .../rules/Azure.Redis.Rule.ps1 | 5 + .../Azure.Redis.Tests.ps1 | 13 +++ 5 files changed, 127 insertions(+) create mode 100644 docs/en/rules/Azure.Redis.Retirement.md diff --git a/docs/changelog.md b/docs/changelog.md index 2085b9424d7..4612173c91f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -34,6 +34,9 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers - App Configuration: - Check that replica locations are in allowed regions by @BernieWhite. [#3441](https://github.com/Azure/PSRule.Rules.Azure/issues/3441) + - Azure Cache for Redis: + - Check for Azure Cache for Redis retirement path by @BenjaminEngeset. + [#3605](https://github.com/Azure/PSRule.Rules.Azure/issues/3605) - Managed Instance for Apache Cassandra: - Check that Managed Instance for Apache Cassandra clusters have availability zones enabled by @BenjaminEngeset. [#3592](https://github.com/Azure/PSRule.Rules.Azure/issues/3592) diff --git a/docs/en/rules/Azure.Redis.Retirement.md b/docs/en/rules/Azure.Redis.Retirement.md new file mode 100644 index 00000000000..cf6d9872368 --- /dev/null +++ b/docs/en/rules/Azure.Redis.Retirement.md @@ -0,0 +1,105 @@ +--- +severity: Important +pillar: Operational Excellence +category: Infrastructure provisioning +resource: Azure Cache for Redis +resourceType: Microsoft.Cache/Redis +online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Redis.Retirement/ +--- + +# Migrate to Azure Managed Redis + +## SYNOPSIS + +Azure Cache for Redis is on the retirement path. Migrate to Azure Managed Redis. + +## DESCRIPTION + +Microsoft has announced the retirement timeline for Azure Cache for Redis across all SKUs. +The recommended replacement going forward is Azure Managed Redis. + +Azure Cache for Redis will be retired according to the following timeline: + +- Basic and Standard SKUs will be retired on September 30, 2025. +- Premium SKU will be retired on September 30, 2027. + +To avoid service disruption, migrate your workloads to Azure Managed Redis. + +Azure Managed Redis provides several advantages: + +- **Improved Performance**: Enhanced throughput and lower latency. +- **Enhanced Security**: Built-in support for Azure Active Directory authentication and managed identities. +- **Better Availability**: Higher availability SLA and improved zone redundancy support. +- **Simplified Management**: Streamlined configuration and maintenance with automated updates. +- **Cost Optimization**: More predictable pricing and better resource utilization. + +## RECOMMENDATION + +Plan and execute migration from Azure Cache for Redis to Azure Managed Redis before the retirement dates to avoid service disruption. + +## EXAMPLES + +### Configure with Azure template + +Azure Managed Redis uses a different resource type. Update your templates to use `Microsoft.Cache/redisEnterprise` instead of `Microsoft.Cache/Redis`. + +For example: + +```json +{ + "type": "Microsoft.Cache/redisEnterprise", + "apiVersion": "2023-11-01", + "name": "[parameters('redisCacheName')]", + "location": "[parameters('location')]", + "sku": { + "name": "Enterprise_E10", + "capacity": 2 + }, + "zones": [ + "1", + "2", + "3" + ], + "properties": { + "minimumTlsVersion": "1.2" + } +} +``` + +### Configure with Bicep + +Azure Managed Redis uses a different resource type. Update your Bicep files to use `Microsoft.Cache/redisEnterprise` instead of `Microsoft.Cache/Redis`. + +For example: + +```bicep +resource redisEnterprise 'Microsoft.Cache/redisEnterprise@2023-11-01' = { + name: redisCacheName + location: location + sku: { + name: 'Enterprise_E10' + capacity: 2 + } + zones: [ + '1' + '2' + '3' + ] + properties: { + minimumTlsVersion: '1.2' + } +} +``` + +## NOTES + +This rule will fail for all Azure Cache for Redis resources as part of informing you about the retirement path. +Consider migrating to Azure Managed Redis before the retirement dates. + +## LINKS + +- [Infrastructure provisioning](https://learn.microsoft.com/azure/architecture/framework/devops/automation-infrastructure) +- [Azure Cache for Redis retirement: What to know and how to prepare](https://techcommunity.microsoft.com/blog/azure-managed-redis/azure-cache-for-redis-retirement-what-to-know-and-how-to-prepare/4458721) +- [Azure Cache for Redis retirement FAQ](https://learn.microsoft.com/azure/azure-cache-for-redis/retirement-faq) +- [Azure Managed Redis documentation](https://learn.microsoft.com/azure/azure-cache-for-redis/managed-redis/managed-redis-overview) +- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.cache/redisenterprise) diff --git a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 index 2aa982b1892..6647ab367b0 100644 --- a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 +++ b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 @@ -131,4 +131,5 @@ ResourceHasNoTags = "The resource does not have any tags. Expected tags: {0}." ActiveSecurityAlerts = "There are {0} active security alerts of high or medium severity." KeyValueShouldNotContainSecrets = "The key value '{0}' property should not contain secrets." + AzureCacheRedisRetirement = "Azure Cache for Redis is on the retirement path. Migrate to Azure Managed Redis." } diff --git a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 index caba1003df9..6d84825bb36 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 @@ -123,6 +123,11 @@ Rule 'Azure.Redis.Version' -Ref 'AZR-000347' -Type 'Microsoft.Cache/redis' -Tag ).Reason($LocalizedData.AzureCacheRedisVersion) } +# Synopsis: Azure Cache for Redis is on the retirement path. Migrate to Azure Managed Redis. +Rule 'Azure.Redis.Retirement' -Ref 'AZR-000505' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { + $Assert.Fail($LocalizedData.AzureCacheRedisRetirement) +} + #region Helper functions function global:GetCacheMemory { diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 index 44bbcbeaac3..c76d0661ba2 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 @@ -353,6 +353,19 @@ Describe 'Azure.Redis' -Tag 'Redis' { $ruleResult.TargetName | Should -BeIn 'redis-R'; $ruleResult.Length | Should -Be 1; } + + It 'Azure.Redis.Retirement' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Redis.Retirement' }; + + # Fail - All Azure Cache for Redis instances should fail this rule + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 12; + $ruleResult.TargetName | Should -BeIn 'redis-A', 'redis-B', 'redis-C', 'redis-D', 'redis-E', 'redis-F', 'redis-G', 'redis-H', 'redis-I', 'redis-J', 'redis-Q', 'redis-R'; + + # Verify the reason message + $ruleResult[0].Reason | Should -BeExactly "Azure Cache for Redis is on the retirement path. Migrate to Azure Managed Redis."; + } } Context 'With Configuration Option' -Tag 'Configuration' { From 1dbd2b1abaabf1aaa3dcf6feaf13fe07cce42bb2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 17:31:08 +0000 Subject: [PATCH 3/9] Fix resource type naming in documentation Co-authored-by: BenjaminEngeset <99641908+BenjaminEngeset@users.noreply.github.com> --- docs/en/rules/Azure.Redis.Retirement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/rules/Azure.Redis.Retirement.md b/docs/en/rules/Azure.Redis.Retirement.md index cf6d9872368..7add9469b24 100644 --- a/docs/en/rules/Azure.Redis.Retirement.md +++ b/docs/en/rules/Azure.Redis.Retirement.md @@ -3,7 +3,7 @@ severity: Important pillar: Operational Excellence category: Infrastructure provisioning resource: Azure Cache for Redis -resourceType: Microsoft.Cache/Redis +resourceType: Microsoft.Cache/redis online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Redis.Retirement/ --- From d07204540b9f986d111e9410df33fa905d92128a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Nov 2025 19:43:28 +0000 Subject: [PATCH 4/9] Address feedback: update rule reference, synopsis, and documentation Co-authored-by: BenjaminEngeset <99641908+BenjaminEngeset@users.noreply.github.com> --- docs/en/rules/Azure.Redis.Retirement.md | 70 ++----------------- src/PSRule.Rules.Azure/en/PSRule-rules.psd1 | 2 +- .../rules/Azure.Redis.Rule.ps1 | 4 +- .../Azure.Redis.Tests.ps1 | 2 +- 4 files changed, 8 insertions(+), 70 deletions(-) diff --git a/docs/en/rules/Azure.Redis.Retirement.md b/docs/en/rules/Azure.Redis.Retirement.md index 7add9469b24..e14cfe57fb5 100644 --- a/docs/en/rules/Azure.Redis.Retirement.md +++ b/docs/en/rules/Azure.Redis.Retirement.md @@ -1,7 +1,8 @@ --- +reviewed: 2025-11-22 severity: Important pillar: Operational Excellence -category: Infrastructure provisioning +category: OE:05 Infrastructure as code resource: Azure Cache for Redis resourceType: Microsoft.Cache/redis online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Redis.Retirement/ @@ -11,7 +12,7 @@ online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Redis. ## SYNOPSIS -Azure Cache for Redis is on the retirement path. Migrate to Azure Managed Redis. +Azure Cache for Redis is being retired. Migrate to Azure Managed Redis. ## DESCRIPTION @@ -25,72 +26,10 @@ Azure Cache for Redis will be retired according to the following timeline: To avoid service disruption, migrate your workloads to Azure Managed Redis. -Azure Managed Redis provides several advantages: - -- **Improved Performance**: Enhanced throughput and lower latency. -- **Enhanced Security**: Built-in support for Azure Active Directory authentication and managed identities. -- **Better Availability**: Higher availability SLA and improved zone redundancy support. -- **Simplified Management**: Streamlined configuration and maintenance with automated updates. -- **Cost Optimization**: More predictable pricing and better resource utilization. - ## RECOMMENDATION Plan and execute migration from Azure Cache for Redis to Azure Managed Redis before the retirement dates to avoid service disruption. -## EXAMPLES - -### Configure with Azure template - -Azure Managed Redis uses a different resource type. Update your templates to use `Microsoft.Cache/redisEnterprise` instead of `Microsoft.Cache/Redis`. - -For example: - -```json -{ - "type": "Microsoft.Cache/redisEnterprise", - "apiVersion": "2023-11-01", - "name": "[parameters('redisCacheName')]", - "location": "[parameters('location')]", - "sku": { - "name": "Enterprise_E10", - "capacity": 2 - }, - "zones": [ - "1", - "2", - "3" - ], - "properties": { - "minimumTlsVersion": "1.2" - } -} -``` - -### Configure with Bicep - -Azure Managed Redis uses a different resource type. Update your Bicep files to use `Microsoft.Cache/redisEnterprise` instead of `Microsoft.Cache/Redis`. - -For example: - -```bicep -resource redisEnterprise 'Microsoft.Cache/redisEnterprise@2023-11-01' = { - name: redisCacheName - location: location - sku: { - name: 'Enterprise_E10' - capacity: 2 - } - zones: [ - '1' - '2' - '3' - ] - properties: { - minimumTlsVersion: '1.2' - } -} -``` - ## NOTES This rule will fail for all Azure Cache for Redis resources as part of informing you about the retirement path. @@ -98,8 +37,7 @@ Consider migrating to Azure Managed Redis before the retirement dates. ## LINKS -- [Infrastructure provisioning](https://learn.microsoft.com/azure/architecture/framework/devops/automation-infrastructure) +- [Infrastructure as code](https://learn.microsoft.com/azure/architecture/framework/devops/automation-infrastructure) - [Azure Cache for Redis retirement: What to know and how to prepare](https://techcommunity.microsoft.com/blog/azure-managed-redis/azure-cache-for-redis-retirement-what-to-know-and-how-to-prepare/4458721) - [Azure Cache for Redis retirement FAQ](https://learn.microsoft.com/azure/azure-cache-for-redis/retirement-faq) - [Azure Managed Redis documentation](https://learn.microsoft.com/azure/azure-cache-for-redis/managed-redis/managed-redis-overview) -- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.cache/redisenterprise) diff --git a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 index 6647ab367b0..be74b3cca3e 100644 --- a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 +++ b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 @@ -131,5 +131,5 @@ ResourceHasNoTags = "The resource does not have any tags. Expected tags: {0}." ActiveSecurityAlerts = "There are {0} active security alerts of high or medium severity." KeyValueShouldNotContainSecrets = "The key value '{0}' property should not contain secrets." - AzureCacheRedisRetirement = "Azure Cache for Redis is on the retirement path. Migrate to Azure Managed Redis." + AzureCacheRedisRetirement = "Azure Cache for Redis is being retired. Migrate to Azure Managed Redis." } diff --git a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 index 6d84825bb36..4ed79666af4 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 @@ -123,8 +123,8 @@ Rule 'Azure.Redis.Version' -Ref 'AZR-000347' -Type 'Microsoft.Cache/redis' -Tag ).Reason($LocalizedData.AzureCacheRedisVersion) } -# Synopsis: Azure Cache for Redis is on the retirement path. Migrate to Azure Managed Redis. -Rule 'Azure.Redis.Retirement' -Ref 'AZR-000505' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { +# Synopsis: Azure Cache for Redis is being retired. Migrate to Azure Managed Redis. +Rule 'Azure.Redis.Retirement' -Ref 'AZR-000506' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { $Assert.Fail($LocalizedData.AzureCacheRedisRetirement) } diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 index c76d0661ba2..c3d21cb6016 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 @@ -364,7 +364,7 @@ Describe 'Azure.Redis' -Tag 'Redis' { $ruleResult.TargetName | Should -BeIn 'redis-A', 'redis-B', 'redis-C', 'redis-D', 'redis-E', 'redis-F', 'redis-G', 'redis-H', 'redis-I', 'redis-J', 'redis-Q', 'redis-R'; # Verify the reason message - $ruleResult[0].Reason | Should -BeExactly "Azure Cache for Redis is on the retirement path. Migrate to Azure Managed Redis."; + $ruleResult[0].Reason | Should -BeExactly "Azure Cache for Redis is being retired. Migrate to Azure Managed Redis."; } } From 7ac3e86c3f146f5fa38af636b34103a06a2cca9d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 23 Nov 2025 17:49:42 +0000 Subject: [PATCH 5/9] Address feedback: rename rule, update dates, and clarify changelog Co-authored-by: BenjaminEngeset <99641908+BenjaminEngeset@users.noreply.github.com> --- docs/changelog.md | 2 +- ...etirement.md => Azure.Redis.MigrateAMR.md} | 19 ++++++++----------- .../rules/Azure.Redis.Rule.ps1 | 2 +- .../Azure.Redis.Tests.ps1 | 4 ++-- 4 files changed, 12 insertions(+), 15 deletions(-) rename docs/en/rules/{Azure.Redis.Retirement.md => Azure.Redis.MigrateAMR.md} (68%) diff --git a/docs/changelog.md b/docs/changelog.md index 4612173c91f..ae9fb112a8f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -35,7 +35,7 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers - Check that replica locations are in allowed regions by @BernieWhite. [#3441](https://github.com/Azure/PSRule.Rules.Azure/issues/3441) - Azure Cache for Redis: - - Check for Azure Cache for Redis retirement path by @BenjaminEngeset. + - Check that Azure Cache for Redis is migrated to Azure Managed Redis by @BenjaminEngeset. [#3605](https://github.com/Azure/PSRule.Rules.Azure/issues/3605) - Managed Instance for Apache Cassandra: - Check that Managed Instance for Apache Cassandra clusters have availability zones enabled by @BenjaminEngeset. diff --git a/docs/en/rules/Azure.Redis.Retirement.md b/docs/en/rules/Azure.Redis.MigrateAMR.md similarity index 68% rename from docs/en/rules/Azure.Redis.Retirement.md rename to docs/en/rules/Azure.Redis.MigrateAMR.md index e14cfe57fb5..be554bbdfa5 100644 --- a/docs/en/rules/Azure.Redis.Retirement.md +++ b/docs/en/rules/Azure.Redis.MigrateAMR.md @@ -1,11 +1,11 @@ --- -reviewed: 2025-11-22 +reviewed: 2025-11-23 severity: Important pillar: Operational Excellence category: OE:05 Infrastructure as code resource: Azure Cache for Redis resourceType: Microsoft.Cache/redis -online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Redis.Retirement/ +online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.Redis.MigrateAMR/ --- # Migrate to Azure Managed Redis @@ -19,10 +19,12 @@ Azure Cache for Redis is being retired. Migrate to Azure Managed Redis. Microsoft has announced the retirement timeline for Azure Cache for Redis across all SKUs. The recommended replacement going forward is Azure Managed Redis. -Azure Cache for Redis will be retired according to the following timeline: +Azure Cache for Redis (Basic, Standard, Premium): -- Basic and Standard SKUs will be retired on September 30, 2025. -- Premium SKU will be retired on September 30, 2027. +- Creation blocked for new customers: April 1, 2026 +- Creation blocked for existing customers: October 1, 2026 +- Retirement Date: September 30, 2028 +- Instances will be disabled starting October 1, 2028 To avoid service disruption, migrate your workloads to Azure Managed Redis. @@ -30,14 +32,9 @@ To avoid service disruption, migrate your workloads to Azure Managed Redis. Plan and execute migration from Azure Cache for Redis to Azure Managed Redis before the retirement dates to avoid service disruption. -## NOTES - -This rule will fail for all Azure Cache for Redis resources as part of informing you about the retirement path. -Consider migrating to Azure Managed Redis before the retirement dates. - ## LINKS -- [Infrastructure as code](https://learn.microsoft.com/azure/architecture/framework/devops/automation-infrastructure) +- [OE:05 Infrastructure as code](https://learn.microsoft.com/azure/architecture/framework/devops/automation-infrastructure) - [Azure Cache for Redis retirement: What to know and how to prepare](https://techcommunity.microsoft.com/blog/azure-managed-redis/azure-cache-for-redis-retirement-what-to-know-and-how-to-prepare/4458721) - [Azure Cache for Redis retirement FAQ](https://learn.microsoft.com/azure/azure-cache-for-redis/retirement-faq) - [Azure Managed Redis documentation](https://learn.microsoft.com/azure/azure-cache-for-redis/managed-redis/managed-redis-overview) diff --git a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 index 4ed79666af4..0bd91439d45 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 @@ -124,7 +124,7 @@ Rule 'Azure.Redis.Version' -Ref 'AZR-000347' -Type 'Microsoft.Cache/redis' -Tag } # Synopsis: Azure Cache for Redis is being retired. Migrate to Azure Managed Redis. -Rule 'Azure.Redis.Retirement' -Ref 'AZR-000506' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { +Rule 'Azure.Redis.MigrateAMR' -Ref 'AZR-000506' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { $Assert.Fail($LocalizedData.AzureCacheRedisRetirement) } diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 index c3d21cb6016..eb841187152 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 @@ -354,8 +354,8 @@ Describe 'Azure.Redis' -Tag 'Redis' { $ruleResult.Length | Should -Be 1; } - It 'Azure.Redis.Retirement' { - $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Redis.Retirement' }; + It 'Azure.Redis.MigrateAMR' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Redis.MigrateAMR' }; # Fail - All Azure Cache for Redis instances should fail this rule $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); From 9db7937414ebb80888980cb9fe4735ed4846ecd9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 23 Nov 2025 18:27:06 +0000 Subject: [PATCH 6/9] Address feedback: improve timeline clarity and rename localized string Co-authored-by: BenjaminEngeset <99641908+BenjaminEngeset@users.noreply.github.com> --- docs/changelog.md | 2 +- docs/en/rules/Azure.Redis.MigrateAMR.md | 10 +++++----- src/PSRule.Rules.Azure/en/PSRule-rules.psd1 | 2 +- src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index ae9fb112a8f..444353d610d 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -35,7 +35,7 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers - Check that replica locations are in allowed regions by @BernieWhite. [#3441](https://github.com/Azure/PSRule.Rules.Azure/issues/3441) - Azure Cache for Redis: - - Check that Azure Cache for Redis is migrated to Azure Managed Redis by @BenjaminEngeset. + - Check that legacy Azure Cache for Redis instances are migrated to Azure Managed Redis by @BenjaminEngeset. [#3605](https://github.com/Azure/PSRule.Rules.Azure/issues/3605) - Managed Instance for Apache Cassandra: - Check that Managed Instance for Apache Cassandra clusters have availability zones enabled by @BenjaminEngeset. diff --git a/docs/en/rules/Azure.Redis.MigrateAMR.md b/docs/en/rules/Azure.Redis.MigrateAMR.md index be554bbdfa5..2731ca5b178 100644 --- a/docs/en/rules/Azure.Redis.MigrateAMR.md +++ b/docs/en/rules/Azure.Redis.MigrateAMR.md @@ -19,12 +19,12 @@ Azure Cache for Redis is being retired. Migrate to Azure Managed Redis. Microsoft has announced the retirement timeline for Azure Cache for Redis across all SKUs. The recommended replacement going forward is Azure Managed Redis. -Azure Cache for Redis (Basic, Standard, Premium): +Azure Cache for Redis (Basic, Standard, Premium) will be retired according to the following timeline: -- Creation blocked for new customers: April 1, 2026 -- Creation blocked for existing customers: October 1, 2026 -- Retirement Date: September 30, 2028 -- Instances will be disabled starting October 1, 2028 +- Creation blocked for new customers: April 1, 2026. +- Creation blocked for existing customers: October 1, 2026. +- Retirement Date: September 30, 2028. +- Instances will be disabled starting October 1, 2028. To avoid service disruption, migrate your workloads to Azure Managed Redis. diff --git a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 index be74b3cca3e..a6414d0f48b 100644 --- a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 +++ b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 @@ -131,5 +131,5 @@ ResourceHasNoTags = "The resource does not have any tags. Expected tags: {0}." ActiveSecurityAlerts = "There are {0} active security alerts of high or medium severity." KeyValueShouldNotContainSecrets = "The key value '{0}' property should not contain secrets." - AzureCacheRedisRetirement = "Azure Cache for Redis is being retired. Migrate to Azure Managed Redis." + AzureCacheRedisMigrateAMR = "Azure Cache for Redis is being retired. Migrate to Azure Managed Redis." } diff --git a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 index 0bd91439d45..f1e1e5a223a 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 @@ -125,7 +125,7 @@ Rule 'Azure.Redis.Version' -Ref 'AZR-000347' -Type 'Microsoft.Cache/redis' -Tag # Synopsis: Azure Cache for Redis is being retired. Migrate to Azure Managed Redis. Rule 'Azure.Redis.MigrateAMR' -Ref 'AZR-000506' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { - $Assert.Fail($LocalizedData.AzureCacheRedisRetirement) + $Assert.Fail($LocalizedData.AzureCacheRedisMigrateAMR) } #region Helper functions From 277a29132578d3075bfbe9bb0bba226c6d37f798 Mon Sep 17 00:00:00 2001 From: Benjamin Engeset Date: Sun, 23 Nov 2025 19:47:36 +0100 Subject: [PATCH 7/9] fixes --- docs/changelog.md | 2 +- tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 444353d610d..a6d28424f89 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -35,7 +35,7 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers - Check that replica locations are in allowed regions by @BernieWhite. [#3441](https://github.com/Azure/PSRule.Rules.Azure/issues/3441) - Azure Cache for Redis: - - Check that legacy Azure Cache for Redis instances are migrated to Azure Managed Redis by @BenjaminEngeset. + - Check for legacy Azure Cache for Redis instances by @BenjaminEngeset. [#3605](https://github.com/Azure/PSRule.Rules.Azure/issues/3605) - Managed Instance for Apache Cassandra: - Check that Managed Instance for Apache Cassandra clusters have availability zones enabled by @BenjaminEngeset. diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 index eb841187152..dede38e472d 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.Redis.Tests.ps1 @@ -357,13 +357,12 @@ Describe 'Azure.Redis' -Tag 'Redis' { It 'Azure.Redis.MigrateAMR' { $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.Redis.MigrateAMR' }; - # Fail - All Azure Cache for Redis instances should fail this rule + # Fail - all instances should fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; $ruleResult.Length | Should -Be 12; $ruleResult.TargetName | Should -BeIn 'redis-A', 'redis-B', 'redis-C', 'redis-D', 'redis-E', 'redis-F', 'redis-G', 'redis-H', 'redis-I', 'redis-J', 'redis-Q', 'redis-R'; - # Verify the reason message $ruleResult[0].Reason | Should -BeExactly "Azure Cache for Redis is being retired. Migrate to Azure Managed Redis."; } } From 220006bacd2ece34c15c7b927d6b6ef499846afe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 23 Nov 2025 19:12:55 +0000 Subject: [PATCH 8/9] Rename localized string to CacheRedisMigrateAMR Co-authored-by: BenjaminEngeset <99641908+BenjaminEngeset@users.noreply.github.com> --- src/PSRule.Rules.Azure/en/PSRule-rules.psd1 | 2 +- src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 index a6414d0f48b..b6c103ef3be 100644 --- a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 +++ b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 @@ -131,5 +131,5 @@ ResourceHasNoTags = "The resource does not have any tags. Expected tags: {0}." ActiveSecurityAlerts = "There are {0} active security alerts of high or medium severity." KeyValueShouldNotContainSecrets = "The key value '{0}' property should not contain secrets." - AzureCacheRedisMigrateAMR = "Azure Cache for Redis is being retired. Migrate to Azure Managed Redis." + CacheRedisMigrateAMR = "Azure Cache for Redis is being retired. Migrate to Azure Managed Redis." } diff --git a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 index f1e1e5a223a..367310370a9 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 @@ -125,7 +125,7 @@ Rule 'Azure.Redis.Version' -Ref 'AZR-000347' -Type 'Microsoft.Cache/redis' -Tag # Synopsis: Azure Cache for Redis is being retired. Migrate to Azure Managed Redis. Rule 'Azure.Redis.MigrateAMR' -Ref 'AZR-000506' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { - $Assert.Fail($LocalizedData.AzureCacheRedisMigrateAMR) + $Assert.Fail($LocalizedData.CacheRedisMigrateAMR) } #region Helper functions From 49a8b6c3945b0703e7c43e5ff619504cef9a8083 Mon Sep 17 00:00:00 2001 From: Bernie White Date: Mon, 24 Nov 2025 00:27:24 +0000 Subject: [PATCH 9/9] Updates --- docs/en/rules/Azure.Redis.MigrateAMR.md | 60 ++++++++++++ docs/examples/resources/amr.bicep | 72 ++++++++++++++ docs/examples/resources/amr.json | 97 +++++++++++++++++++ .../rules/Azure.Redis.Rule.ps1 | 2 +- 4 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 docs/examples/resources/amr.bicep create mode 100644 docs/examples/resources/amr.json diff --git a/docs/en/rules/Azure.Redis.MigrateAMR.md b/docs/en/rules/Azure.Redis.MigrateAMR.md index 2731ca5b178..dbc4c26b5a5 100644 --- a/docs/en/rules/Azure.Redis.MigrateAMR.md +++ b/docs/en/rules/Azure.Redis.MigrateAMR.md @@ -32,9 +32,69 @@ To avoid service disruption, migrate your workloads to Azure Managed Redis. Plan and execute migration from Azure Cache for Redis to Azure Managed Redis before the retirement dates to avoid service disruption. +## EXAMPLES + +### Configure with Bicep + +To deploy resource that pass this rule: + +- Create resources of type `Microsoft.Cache/redisEnterprise` and an Azure Managed Redis SKU, such as: + - `Balanced_*` + - `MemoryOptimized_*` + - `ComputeOptimized_*` + +For example: + +```bicep +resource primary 'Microsoft.Cache/redisEnterprise@2025-07-01' = { + name: name + location: location + properties: { + highAvailability: 'Enabled' + publicNetworkAccess: 'Disabled' + } + sku: { + name: 'Balanced_B10' + } +} +``` + +### Configure with Azure template + +To deploy resource that pass this rule: + +- Create resources of type `Microsoft.Cache/redisEnterprise` and an Azure Managed Redis SKU, such as: + - `Balanced_*` + - `MemoryOptimized_*` + - `ComputeOptimized_*` + +For example: + +```json +{ + "type": "Microsoft.Cache/redisEnterprise", + "apiVersion": "2025-07-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "properties": { + "highAvailability": "Enabled", + "publicNetworkAccess": "Disabled" + }, + "sku": { + "name": "Balanced_B10" + } +} +``` + +## NOTES + +Redis Enterprise and Enterprise Flash used the `Microsoft.Cache/redisEnterprise` resource type. +Redis Enterprise and Enterprise Flash SKUs `Enterprise_*` and `EnterpriseFlash_*` are also deprecated. + ## LINKS - [OE:05 Infrastructure as code](https://learn.microsoft.com/azure/architecture/framework/devops/automation-infrastructure) - [Azure Cache for Redis retirement: What to know and how to prepare](https://techcommunity.microsoft.com/blog/azure-managed-redis/azure-cache-for-redis-retirement-what-to-know-and-how-to-prepare/4458721) - [Azure Cache for Redis retirement FAQ](https://learn.microsoft.com/azure/azure-cache-for-redis/retirement-faq) - [Azure Managed Redis documentation](https://learn.microsoft.com/azure/azure-cache-for-redis/managed-redis/managed-redis-overview) +- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.cache/redisenterprise) diff --git a/docs/examples/resources/amr.bicep b/docs/examples/resources/amr.bicep new file mode 100644 index 00000000000..49ce229c74e --- /dev/null +++ b/docs/examples/resources/amr.bicep @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Bicep documentation examples + +@minLength(1) +@maxLength(63) +@sys.description('The name of the resource.') +param name string + +@sys.description('The location resources will be deployed.') +param location string = resourceGroup().location + +@sys.description('The location of a secondary replica.') +param secondaryLocation string = location + +// An example Azure Managed Redis instance with availability zones. +resource primary 'Microsoft.Cache/redisEnterprise@2025-07-01' = { + name: name + location: location + properties: { + highAvailability: 'Enabled' + publicNetworkAccess: 'Disabled' + } + sku: { + name: 'Balanced_B10' + } +} + +// An example secondary replica in an alternative region. +resource secondary 'Microsoft.Cache/redisEnterprise@2025-07-01' = { + name: name + location: secondaryLocation + properties: { + highAvailability: 'Enabled' + publicNetworkAccess: 'Disabled' + } + sku: { + name: 'Balanced_B10' + } +} + +// An example database replicated across the primary and secondary instances. +resource database 'Microsoft.Cache/redisEnterprise/databases@2025-07-01' = { + parent: primary + name: 'default' + properties: { + clientProtocol: 'Encrypted' + evictionPolicy: 'VolatileLRU' + clusteringPolicy: 'OSSCluster' + deferUpgrade: 'NotDeferred' + modules: [ + { + name: 'RedisJSON' + } + ] + persistence: { + aofEnabled: false + rdbEnabled: true + rdbFrequency: '12h' + } + accessKeysAuthentication: 'Disabled' + geoReplication: { + groupNickname: 'group' + linkedDatabases: [ + { + id: resourceId('Microsoft.Cache/redisEnterprise/databases', secondary.name, 'default') + } + ] + } + } +} diff --git a/docs/examples/resources/amr.json b/docs/examples/resources/amr.json new file mode 100644 index 00000000000..748e1993033 --- /dev/null +++ b/docs/examples/resources/amr.json @@ -0,0 +1,97 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.39.26.7824", + "templateHash": "6517319720095351040" + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 63, + "metadata": { + "description": "The name of the resource." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "The location resources will be deployed." + } + }, + "secondaryLocation": { + "type": "string", + "defaultValue": "[parameters('location')]", + "metadata": { + "description": "The location of a secondary replica." + } + } + }, + "resources": [ + { + "type": "Microsoft.Cache/redisEnterprise", + "apiVersion": "2025-07-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "properties": { + "highAvailability": "Enabled", + "publicNetworkAccess": "Disabled" + }, + "sku": { + "name": "Balanced_B10" + } + }, + { + "type": "Microsoft.Cache/redisEnterprise", + "apiVersion": "2025-07-01", + "name": "[parameters('name')]", + "location": "[parameters('secondaryLocation')]", + "properties": { + "highAvailability": "Enabled", + "publicNetworkAccess": "Disabled" + }, + "sku": { + "name": "Balanced_B10" + } + }, + { + "type": "Microsoft.Cache/redisEnterprise/databases", + "apiVersion": "2025-07-01", + "name": "[format('{0}/{1}', parameters('name'), 'default')]", + "properties": { + "clientProtocol": "Encrypted", + "evictionPolicy": "VolatileLRU", + "clusteringPolicy": "OSSCluster", + "deferUpgrade": "NotDeferred", + "modules": [ + { + "name": "RedisJSON" + } + ], + "persistence": { + "aofEnabled": false, + "rdbEnabled": true, + "rdbFrequency": "12h" + }, + "accessKeysAuthentication": "Disabled", + "geoReplication": { + "groupNickname": "group", + "linkedDatabases": [ + { + "id": "[resourceId('Microsoft.Cache/redisEnterprise/databases', parameters('name'), 'default')]" + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Cache/redisEnterprise', parameters('name'))]", + "[resourceId('Microsoft.Cache/redisEnterprise', parameters('name'))]" + ] + } + ] +} \ No newline at end of file diff --git a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 index 367310370a9..4e53f43fb6f 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.Redis.Rule.ps1 @@ -124,7 +124,7 @@ Rule 'Azure.Redis.Version' -Ref 'AZR-000347' -Type 'Microsoft.Cache/redis' -Tag } # Synopsis: Azure Cache for Redis is being retired. Migrate to Azure Managed Redis. -Rule 'Azure.Redis.MigrateAMR' -Ref 'AZR-000506' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { +Rule 'Azure.Redis.MigrateAMR' -Ref 'AZR-000533' -Type 'Microsoft.Cache/redis' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Operational Excellence'; } { $Assert.Fail($LocalizedData.CacheRedisMigrateAMR) }