From 3fb7c6e2835cc641b6f290c46328537d428e864e Mon Sep 17 00:00:00 2001 From: JeffreyCA Date: Wed, 29 Jan 2025 12:33:06 -0800 Subject: [PATCH] feat: `avm/res/cache/redis`: Support exporting StackExchange.Redis connection strings to Key Vault (#4343) ## Description Add support for exporting TLS-enabled [StackExchange.Redis connection strings](https://stackexchange.github.io/StackExchange.Redis/Configuration.html#basic-configuration-strings) to Key Vault: ``` .redis.cache.windows.net:6380,password=,ssl=True,abortConnect=False ``` I've kept the same parameters as what's shown in portal's Authentication blade: ![image](https://github.com/user-attachments/assets/6a2d5256-ec62-44b5-94a6-5bebe6838d9c) Usage example: ```bicep module redis 'br/public:avm/res/cache/redis:' = { name: 'redisDeployment' params: { // Required parameters name: 'kvref' // Non-required parameters location: '' secretsExportConfiguration: { keyVaultResourceId: '' primaryStackExchangeRedisConnectionStringName: 'custom-primaryStackExchangeRedisConnectionString-name' secondaryStackExchangeRedisConnectionStringName: 'custom-secondaryStackExchangeRedisConnectionString-name' } } } ``` ## Pipeline Reference Ran the `kv-secrets` E2E test locally and passed: ![image](https://github.com/user-attachments/assets/df6d8dd8-64cc-44a9-b210-b917ded81190) | Pipeline | | -------- | | | ## Type of Change - [ ] Update to CI Environment or utilities (Non-module affecting changes) - [x] Azure Verified Module updates: - [ ] Bugfix containing backwards-compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [x] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [ ] My corresponding pipelines / checks run clean and green without any errors or warnings --- avm/res/cache/redis/README.md | 26 ++++++++++++++++++- avm/res/cache/redis/linked-servers/main.json | 4 +-- avm/res/cache/redis/main.bicep | 22 ++++++++++++++++ avm/res/cache/redis/main.json | 18 +++++++++++-- .../tests/e2e/kv-secrets/main.test.bicep | 2 ++ avm/res/cache/redis/version.json | 2 +- 6 files changed, 68 insertions(+), 6 deletions(-) diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index 80714bea97..49297597e7 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -245,8 +245,10 @@ module redis 'br/public:avm/res/cache/redis:' = { keyVaultResourceId: '' primaryAccessKeyName: 'custom-primaryAccessKey-name' primaryConnectionStringName: 'custom-primaryConnectionString-name' + primaryStackExchangeRedisConnectionStringName: 'custom-primaryStackExchangeRedisConnectionString-name' secondaryAccessKeyName: 'custom-secondaryAccessKey-name' secondaryConnectionStringName: 'custom-secondaryConnectionString-name' + secondaryStackExchangeRedisConnectionStringName: 'custom-secondaryStackExchangeRedisConnectionString-name' } } } @@ -277,8 +279,10 @@ module redis 'br/public:avm/res/cache/redis:' = { "keyVaultResourceId": "", "primaryAccessKeyName": "custom-primaryAccessKey-name", "primaryConnectionStringName": "custom-primaryConnectionString-name", + "primaryStackExchangeRedisConnectionStringName": "custom-primaryStackExchangeRedisConnectionString-name", "secondaryAccessKeyName": "custom-secondaryAccessKey-name", - "secondaryConnectionStringName": "custom-secondaryConnectionString-name" + "secondaryConnectionStringName": "custom-secondaryConnectionString-name", + "secondaryStackExchangeRedisConnectionStringName": "custom-secondaryStackExchangeRedisConnectionString-name" } } } @@ -303,8 +307,10 @@ param secretsExportConfiguration = { keyVaultResourceId: '' primaryAccessKeyName: 'custom-primaryAccessKey-name' primaryConnectionStringName: 'custom-primaryConnectionString-name' + primaryStackExchangeRedisConnectionStringName: 'custom-primaryStackExchangeRedisConnectionString-name' secondaryAccessKeyName: 'custom-secondaryAccessKey-name' secondaryConnectionStringName: 'custom-secondaryConnectionString-name' + secondaryStackExchangeRedisConnectionStringName: 'custom-secondaryStackExchangeRedisConnectionString-name' } ``` @@ -2110,8 +2116,10 @@ Key vault reference and secret settings for the module's secrets export. | :-- | :-- | :-- | | [`primaryAccessKeyName`](#parameter-secretsexportconfigurationprimaryaccesskeyname) | string | The primaryAccessKey secret name to create. | | [`primaryConnectionStringName`](#parameter-secretsexportconfigurationprimaryconnectionstringname) | string | The primaryConnectionString secret name to create. | +| [`primaryStackExchangeRedisConnectionStringName`](#parameter-secretsexportconfigurationprimarystackexchangeredisconnectionstringname) | string | The primaryStackExchangeRedisConnectionString secret name to create. | | [`secondaryAccessKeyName`](#parameter-secretsexportconfigurationsecondaryaccesskeyname) | string | The secondaryAccessKey secret name to create. | | [`secondaryConnectionStringName`](#parameter-secretsexportconfigurationsecondaryconnectionstringname) | string | The secondaryConnectionString secret name to create. | +| [`secondaryStackExchangeRedisConnectionStringName`](#parameter-secretsexportconfigurationsecondarystackexchangeredisconnectionstringname) | string | The secondaryStackExchangeRedisConnectionString secret name to create. | ### Parameter: `secretsExportConfiguration.keyVaultResourceId` @@ -2137,6 +2145,14 @@ The primaryConnectionString secret name to create. - Type: string - MinValue: 1 +### Parameter: `secretsExportConfiguration.primaryStackExchangeRedisConnectionStringName` + +The primaryStackExchangeRedisConnectionString secret name to create. + +- Required: No +- Type: string +- MinValue: 1 + ### Parameter: `secretsExportConfiguration.secondaryAccessKeyName` The secondaryAccessKey secret name to create. @@ -2153,6 +2169,14 @@ The secondaryConnectionString secret name to create. - Type: string - MinValue: 1 +### Parameter: `secretsExportConfiguration.secondaryStackExchangeRedisConnectionStringName` + +The secondaryStackExchangeRedisConnectionString secret name to create. + +- Required: No +- Type: string +- MinValue: 1 + ### Parameter: `shardCount` The number of shards to be created on a Premium Cluster Cache. diff --git a/avm/res/cache/redis/linked-servers/main.json b/avm/res/cache/redis/linked-servers/main.json index 19003b2a2a..170402a3d5 100644 --- a/avm/res/cache/redis/linked-servers/main.json +++ b/avm/res/cache/redis/linked-servers/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.32.4.45862", - "templateHash": "395538410437204745" + "version": "0.33.13.18514", + "templateHash": "11294861621866290910" }, "name": "Redis Cache Linked Servers", "description": "This module connects a primary and secondary Redis Cache together for geo-replication." diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index a9b19ae23f..04f8400908 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -398,6 +398,14 @@ module secretsExport 'modules/keyVaultExport.bicep' = if (secretsExportConfigura } ] : [], + contains(secretsExportConfiguration!, 'primaryStackExchangeRedisConnectionStringName') + ? [ + { + name: secretsExportConfiguration!.?primaryStackExchangeRedisConnectionStringName + value: '${redis.properties.hostName}:6380,password=${redis.listKeys().primaryKey},ssl=True,abortConnect=False' + } + ] + : [], contains(secretsExportConfiguration!, 'secondaryAccessKeyName') ? [ { @@ -413,6 +421,14 @@ module secretsExport 'modules/keyVaultExport.bicep' = if (secretsExportConfigura value: 'rediss://:${redis.listKeys().secondaryKey}@${redis.properties.hostName}:6380' } ] + : [], + contains(secretsExportConfiguration!, 'secondaryStackExchangeRedisConnectionStringName') + ? [ + { + name: secretsExportConfiguration!.?secondaryStackExchangeRedisConnectionStringName + value: '${redis.properties.hostName}:6380,password=${redis.listKeys().secondaryKey},ssl=True,abortConnect=False' + } + ] : [] ) } @@ -514,9 +530,15 @@ type secretsExportConfigurationType = { @description('Optional. The primaryConnectionString secret name to create.') primaryConnectionStringName: string? + @description('Optional. The primaryStackExchangeRedisConnectionString secret name to create.') + primaryStackExchangeRedisConnectionStringName: string? + @description('Optional. The secondaryAccessKey secret name to create.') secondaryAccessKeyName: string? @description('Optional. The secondaryConnectionString secret name to create.') secondaryConnectionStringName: string? + + @description('Optional. The secondaryStackExchangeRedisConnectionString secret name to create.') + secondaryStackExchangeRedisConnectionStringName: string? } diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index 62d490f4d3..7519cd3edd 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.33.13.18514", - "templateHash": "6280028405930372235" + "templateHash": "14266403126769654218" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache." @@ -138,6 +138,13 @@ "description": "Optional. The primaryConnectionString secret name to create." } }, + "primaryStackExchangeRedisConnectionStringName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primaryStackExchangeRedisConnectionString secret name to create." + } + }, "secondaryAccessKeyName": { "type": "string", "nullable": true, @@ -151,6 +158,13 @@ "metadata": { "description": "Optional. The secondaryConnectionString secret name to create." } + }, + "secondaryStackExchangeRedisConnectionStringName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The secondaryStackExchangeRedisConnectionString secret name to create." + } } }, "metadata": { @@ -2047,7 +2061,7 @@ "value": "[last(split(coalesce(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '//'), '/'))]" }, "secretsToSet": { - "value": "[union(createArray(), if(contains(parameters('secretsExportConfiguration'), 'primaryAccessKeyName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'primaryAccessKeyName'), 'value', listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').primaryKey)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'primaryConnectionStringName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'primaryConnectionStringName'), 'value', format('rediss://:{0}@{1}:6380', listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').primaryKey, reference('redis').hostName))), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryAccessKeyName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'secondaryAccessKeyName'), 'value', listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').secondaryKey)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryConnectionStringName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'secondaryConnectionStringName'), 'value', format('rediss://:{0}@{1}:6380', listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').secondaryKey, reference('redis').hostName))), createArray()))]" + "value": "[union(createArray(), if(contains(parameters('secretsExportConfiguration'), 'primaryAccessKeyName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'primaryAccessKeyName'), 'value', listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').primaryKey)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'primaryConnectionStringName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'primaryConnectionStringName'), 'value', format('rediss://:{0}@{1}:6380', listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').primaryKey, reference('redis').hostName))), createArray()), if(contains(parameters('secretsExportConfiguration'), 'primaryStackExchangeRedisConnectionStringName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'primaryStackExchangeRedisConnectionStringName'), 'value', format('{0}:6380,password={1},ssl=True,abortConnect=False', reference('redis').hostName, listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').primaryKey))), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryAccessKeyName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'secondaryAccessKeyName'), 'value', listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').secondaryKey)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryConnectionStringName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'secondaryConnectionStringName'), 'value', format('rediss://:{0}@{1}:6380', listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').secondaryKey, reference('redis').hostName))), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryStackExchangeRedisConnectionStringName'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'secondaryStackExchangeRedisConnectionStringName'), 'value', format('{0}:6380,password={1},ssl=True,abortConnect=False', reference('redis').hostName, listKeys(resourceId('Microsoft.Cache/redis', parameters('name')), '2024-11-01').secondaryKey))), createArray()))]" } }, "template": { diff --git a/avm/res/cache/redis/tests/e2e/kv-secrets/main.test.bicep b/avm/res/cache/redis/tests/e2e/kv-secrets/main.test.bicep index 6cc88c35ff..f610f08135 100644 --- a/avm/res/cache/redis/tests/e2e/kv-secrets/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/kv-secrets/main.test.bicep @@ -51,8 +51,10 @@ module testDeployment '../../../main.bicep' = { keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId primaryAccessKeyName: 'custom-primaryAccessKey-name' primaryConnectionStringName: 'custom-primaryConnectionString-name' + primaryStackExchangeRedisConnectionStringName: 'custom-primaryStackExchangeRedisConnectionString-name' secondaryAccessKeyName: 'custom-secondaryAccessKey-name' secondaryConnectionStringName: 'custom-secondaryConnectionString-name' + secondaryStackExchangeRedisConnectionStringName: 'custom-secondaryStackExchangeRedisConnectionString-name' } } } diff --git a/avm/res/cache/redis/version.json b/avm/res/cache/redis/version.json index 91ffa760bf..23f3815885 100644 --- a/avm/res/cache/redis/version.json +++ b/avm/res/cache/redis/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.11", + "version": "0.12", "pathFilters": [ "./main.json" ]