From e6527fa9cfd6d99a825f98c886f9e167a83c4d9e Mon Sep 17 00:00:00 2001 From: Luke Snoddy <37806411+lsnoddy@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:22:44 -0600 Subject: [PATCH] fix: avm.res.service-fabric.cluster failed pipeline - `avm/res/service-fabric/cluster` (#1951) ## Description Updated test cases to fix failed pipeline: - Added certificate param to satisfy secure cluster requirement - Removed redundant cert test case - Cleaned up other certificate params in the test cases Closes https://github.com/Azure/bicep-registry-modules/issues/1726 ## Pipeline Reference | Pipeline | | -------- | [![avm.res.service-fabric.cluster](https://github.com/lsnoddy/bicep-registry-modules/actions/workflows/avm.res.service-fabric.cluster.yml/badge.svg?branch=users%2Flsnoddy%2Fservice-fabric-cluster)](https://github.com/lsnoddy/bicep-registry-modules/actions/workflows/avm.res.service-fabric.cluster.yml) | | ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [x] 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. - [ ] 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. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --------- Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- avm/res/service-fabric/cluster/README.md | 387 +++++++++--------- avm/res/service-fabric/cluster/main.bicep | 160 +++++--- avm/res/service-fabric/cluster/main.json | 183 +++++++-- .../cluster/tests/e2e/cert/main.test.bicep | 71 ---- .../tests/e2e/defaults/main.test.bicep | 3 + .../cluster/tests/e2e/max/main.test.bicep | 12 +- .../tests/e2e/waf-aligned/main.test.bicep | 23 +- avm/res/service-fabric/cluster/version.json | 2 +- 8 files changed, 469 insertions(+), 372 deletions(-) delete mode 100644 avm/res/service-fabric/cluster/tests/e2e/cert/main.test.bicep diff --git a/avm/res/service-fabric/cluster/README.md b/avm/res/service-fabric/cluster/README.md index eba3b7a0b5..759b3d695f 100644 --- a/avm/res/service-fabric/cluster/README.md +++ b/avm/res/service-fabric/cluster/README.md @@ -28,14 +28,13 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/service-fabric/cluster:`. -- [Certificate](#example-1-certificate) -- [Using only defaults](#example-2-using-only-defaults) -- [Using large parameter set](#example-3-using-large-parameter-set) -- [WAF-aligned](#example-4-waf-aligned) +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) -### Example 1: _Certificate_ +### Example 1: _Using only defaults_ -This instance deploys the module with a certificate. +This instance deploys the module with the minimum set of required parameters.
@@ -47,8 +46,8 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { name: 'clusterDeployment' params: { // Required parameters - managementEndpoint: 'https://sfccer001.westeurope.cloudapp.azure.com:19080' - name: 'sfccer001' + managementEndpoint: 'https://sfcmin001.westeurope.cloudapp.azure.com:19080' + name: 'sfcmin001' nodeTypes: [ { applicationPorts: { @@ -70,7 +69,6 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { // Non-required parameters certificate: { thumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' - x509StoreName: 'My' } location: '' } @@ -91,10 +89,10 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { "parameters": { // Required parameters "managementEndpoint": { - "value": "https://sfccer001.westeurope.cloudapp.azure.com:19080" + "value": "https://sfcmin001.westeurope.cloudapp.azure.com:19080" }, "name": { - "value": "sfccer001" + "value": "sfcmin001" }, "nodeTypes": { "value": [ @@ -121,8 +119,7 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { // Non-required parameters "certificate": { "value": { - "thumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", - "x509StoreName": "My" + "thumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130" } }, "location": { @@ -135,99 +132,7 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = {

-### Example 2: _Using only defaults_ - -This instance deploys the module with the minimum set of required parameters. - - -

- -via Bicep module - -```bicep -module cluster 'br/public:avm/res/service-fabric/cluster:' = { - name: 'clusterDeployment' - params: { - // Required parameters - managementEndpoint: 'https://sfcmin001.westeurope.cloudapp.azure.com:19080' - name: 'sfcmin001' - nodeTypes: [ - { - applicationPorts: { - endPort: 30000 - startPort: 20000 - } - clientConnectionEndpointPort: 19000 - durabilityLevel: 'Bronze' - ephemeralPorts: { - endPort: 65534 - startPort: 49152 - } - httpGatewayEndpointPort: 19080 - isPrimary: true - name: 'Node01' - } - ] - reliabilityLevel: 'None' - // Non-required parameters - location: '' - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "managementEndpoint": { - "value": "https://sfcmin001.westeurope.cloudapp.azure.com:19080" - }, - "name": { - "value": "sfcmin001" - }, - "nodeTypes": { - "value": [ - { - "applicationPorts": { - "endPort": 30000, - "startPort": 20000 - }, - "clientConnectionEndpointPort": 19000, - "durabilityLevel": "Bronze", - "ephemeralPorts": { - "endPort": 65534, - "startPort": 49152 - }, - "httpGatewayEndpointPort": 19080, - "isPrimary": true, - "name": "Node01" - } - ] - }, - "reliabilityLevel": { - "value": "None" - }, - // Non-required parameters - "location": { - "value": "" - } - } -} -``` - -
-

- -### Example 3: _Using large parameter set_ +### Example 2: _Using large parameter set_ This instance deploys the module with most of its features enabled. @@ -306,7 +211,7 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { certificateIssuerThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' } ] - x509StoreName: '' + x509StoreName: 'My' } clientCertificateCommonNames: [ { @@ -320,16 +225,6 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { isAdmin: false } ] - clientCertificateThumbprints: [ - { - certificateThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' - isAdmin: false - } - { - certificateThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC131' - isAdmin: false - } - ] diagnosticsStorageAccountConfig: { blobEndpoint: '' protectedAccountKeyName: 'StorageAccountKey1' @@ -516,7 +411,7 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { "certificateIssuerThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130" } ], - "x509StoreName": "" + "x509StoreName": "My" } }, "clientCertificateCommonNames": { @@ -533,18 +428,6 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { } ] }, - "clientCertificateThumbprints": { - "value": [ - { - "certificateThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", - "isAdmin": false - }, - { - "certificateThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC131", - "isAdmin": false - } - ] - }, "diagnosticsStorageAccountConfig": { "value": { "blobEndpoint": "", @@ -661,7 +544,7 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = {

-### Example 4: _WAF-aligned_ +### Example 3: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -733,14 +616,9 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { clusterApplication: 'cf33fea8-b30f-424f-ab73-c48d99e0b222' tenantId: '' } - certificateCommonNames: { - commonNames: [ - { - certificateCommonName: 'certcommon' - certificateIssuerThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' - } - ] - x509StoreName: '' + certificate: { + thumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' + x509StoreName: 'My' } clientCertificateCommonNames: [ { @@ -754,16 +632,6 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { isAdmin: false } ] - clientCertificateThumbprints: [ - { - certificateThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' - isAdmin: false - } - { - certificateThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC131' - isAdmin: false - } - ] diagnosticsStorageAccountConfig: { blobEndpoint: '' protectedAccountKeyName: 'StorageAccountKey1' @@ -921,15 +789,10 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { "tenantId": "" } }, - "certificateCommonNames": { + "certificate": { "value": { - "commonNames": [ - { - "certificateCommonName": "certcommon", - "certificateIssuerThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130" - } - ], - "x509StoreName": "" + "thumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", + "x509StoreName": "My" } }, "clientCertificateCommonNames": { @@ -946,18 +809,6 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { } ] }, - "clientCertificateThumbprints": { - "value": [ - { - "certificateThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC130", - "isAdmin": false - }, - { - "certificateThumbprint": "0AC113D5E1D94C401DDEB0EE2B1B96CC131", - "isAdmin": false - } - ] - }, "diagnosticsStorageAccountConfig": { "value": { "blobEndpoint": "", @@ -1061,6 +912,13 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { | [`nodeTypes`](#parameter-nodetypes) | array | The list of node types in the cluster. | | [`reliabilityLevel`](#parameter-reliabilitylevel) | string | The reliability level sets the replica set size of system services. Learn about ReliabilityLevel (https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-cluster-capacity). - None - Run the System services with a target replica set count of 1. This should only be used for test clusters. - Bronze - Run the System services with a target replica set count of 3. This should only be used for test clusters. - Silver - Run the System services with a target replica set count of 5. - Gold - Run the System services with a target replica set count of 7. - Platinum - Run the System services with a target replica set count of 9. | +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`certificate`](#parameter-certificate) | object | The certificate to use for securing the cluster. The certificate provided will be used for node to node security within the cluster, SSL certificate for cluster management endpoint and default admin client. Required if the certificateCommonNames parameter is not used. | +| [`certificateCommonNames`](#parameter-certificatecommonnames) | object | Describes a list of server certificates referenced by common name that are used to secure the cluster. Required if the certificate parameter is not used. | + **Optional parameters** | Parameter | Type | Description | @@ -1068,10 +926,8 @@ module cluster 'br/public:avm/res/service-fabric/cluster:' = { | [`addOnFeatures`](#parameter-addonfeatures) | array | The list of add-on features to enable in the cluster. | | [`applicationTypes`](#parameter-applicationtypes) | array | Array of Service Fabric cluster application types. | | [`azureActiveDirectory`](#parameter-azureactivedirectory) | object | The settings to enable AAD authentication on the cluster. | -| [`certificate`](#parameter-certificate) | object | Describes the certificate details like thumbprint of the primary certificate, thumbprint of the secondary certificate and the local certificate store location. | -| [`certificateCommonNames`](#parameter-certificatecommonnames) | object | Describes a list of server certificates referenced by common name that are used to secure the cluster. | -| [`clientCertificateCommonNames`](#parameter-clientcertificatecommonnames) | array | The list of client certificates referenced by common name that are allowed to manage the cluster. | -| [`clientCertificateThumbprints`](#parameter-clientcertificatethumbprints) | array | The list of client certificates referenced by thumbprint that are allowed to manage the cluster. | +| [`clientCertificateCommonNames`](#parameter-clientcertificatecommonnames) | array | The list of client certificates referenced by common name that are allowed to manage the cluster. Cannot be used if the clientCertificateThumbprints parameter is used. | +| [`clientCertificateThumbprints`](#parameter-clientcertificatethumbprints) | array | The list of client certificates referenced by thumbprint that are allowed to manage the cluster. Cannot be used if the clientCertificateCommonNames parameter is used. | | [`clusterCodeVersion`](#parameter-clustercodeversion) | string | The Service Fabric runtime version of the cluster. This property can only by set the user when upgradeMode is set to "Manual". To get list of available Service Fabric versions for new clusters use ClusterVersion API. To get the list of available version for existing clusters use availableClusterVersions. | | [`diagnosticsStorageAccountConfig`](#parameter-diagnosticsstorageaccountconfig) | object | The storage account information for storing Service Fabric diagnostic logs. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | @@ -1134,6 +990,127 @@ The reliability level sets the replica set size of system services. Learn about ] ``` +### Parameter: `certificate` + +The certificate to use for securing the cluster. The certificate provided will be used for node to node security within the cluster, SSL certificate for cluster management endpoint and default admin client. Required if the certificateCommonNames parameter is not used. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`thumbprint`](#parameter-certificatethumbprint) | string | The thumbprint of the primary certificate. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`thumbprintSecondary`](#parameter-certificatethumbprintsecondary) | string | The thumbprint of the secondary certificate. | +| [`x509StoreName`](#parameter-certificatex509storename) | string | The local certificate store location. | + +### Parameter: `certificate.thumbprint` + +The thumbprint of the primary certificate. + +- Required: Yes +- Type: string + +### Parameter: `certificate.thumbprintSecondary` + +The thumbprint of the secondary certificate. + +- Required: No +- Type: string + +### Parameter: `certificate.x509StoreName` + +The local certificate store location. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AddressBook' + 'AuthRoot' + 'CertificateAuthority' + 'Disallowed' + 'My' + 'Root' + 'TrustedPeople' + 'TrustedPublisher' + ] + ``` + +### Parameter: `certificateCommonNames` + +Describes a list of server certificates referenced by common name that are used to secure the cluster. Required if the certificate parameter is not used. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`commonNames`](#parameter-certificatecommonnamescommonnames) | array | The list of server certificates referenced by common name that are used to secure the cluster. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`x509StoreName`](#parameter-certificatecommonnamesx509storename) | string | The local certificate store location. | + +### Parameter: `certificateCommonNames.commonNames` + +The list of server certificates referenced by common name that are used to secure the cluster. + +- Required: Yes +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`certificateCommonName`](#parameter-certificatecommonnamescommonnamescertificatecommonname) | string | The common name of the server certificate. | +| [`certificateIssuerThumbprint`](#parameter-certificatecommonnamescommonnamescertificateissuerthumbprint) | string | The issuer thumbprint of the server certificate. | + +### Parameter: `certificateCommonNames.commonNames.certificateCommonName` + +The common name of the server certificate. + +- Required: Yes +- Type: string + +### Parameter: `certificateCommonNames.commonNames.certificateIssuerThumbprint` + +The issuer thumbprint of the server certificate. + +- Required: Yes +- Type: string + +### Parameter: `certificateCommonNames.x509StoreName` + +The local certificate store location. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AddressBook' + 'AuthRoot' + 'CertificateAuthority' + 'Disallowed' + 'My' + 'Root' + 'TrustedPeople' + 'TrustedPublisher' + ] + ``` + ### Parameter: `addOnFeatures` The list of add-on features to enable in the cluster. @@ -1167,37 +1144,69 @@ The settings to enable AAD authentication on the cluster. - Type: object - Default: `{}` -### Parameter: `certificate` +### Parameter: `clientCertificateCommonNames` -Describes the certificate details like thumbprint of the primary certificate, thumbprint of the secondary certificate and the local certificate store location. +The list of client certificates referenced by common name that are allowed to manage the cluster. Cannot be used if the clientCertificateThumbprints parameter is used. - Required: No -- Type: object -- Default: `{}` +- Type: array -### Parameter: `certificateCommonNames` +**Required parameters** -Describes a list of server certificates referenced by common name that are used to secure the cluster. +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`certificateCommonName`](#parameter-clientcertificatecommonnamescertificatecommonname) | string | The common name of the client certificate. | +| [`certificateIssuerThumbprint`](#parameter-clientcertificatecommonnamescertificateissuerthumbprint) | string | The issuer thumbprint of the client certificate. | +| [`isAdmin`](#parameter-clientcertificatecommonnamesisadmin) | bool | Indicates if the client certificate has admin access to the cluster. Non admin clients can perform only read only operations on the cluster. | -- Required: No -- Type: object -- Default: `{}` +### Parameter: `clientCertificateCommonNames.certificateCommonName` -### Parameter: `clientCertificateCommonNames` +The common name of the client certificate. -The list of client certificates referenced by common name that are allowed to manage the cluster. +- Required: Yes +- Type: string -- Required: No -- Type: array -- Default: `[]` +### Parameter: `clientCertificateCommonNames.certificateIssuerThumbprint` + +The issuer thumbprint of the client certificate. + +- Required: Yes +- Type: string + +### Parameter: `clientCertificateCommonNames.isAdmin` + +Indicates if the client certificate has admin access to the cluster. Non admin clients can perform only read only operations on the cluster. + +- Required: Yes +- Type: bool ### Parameter: `clientCertificateThumbprints` -The list of client certificates referenced by thumbprint that are allowed to manage the cluster. +The list of client certificates referenced by thumbprint that are allowed to manage the cluster. Cannot be used if the clientCertificateCommonNames parameter is used. - Required: No - Type: array -- Default: `[]` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`certificateThumbprint`](#parameter-clientcertificatethumbprintscertificatethumbprint) | string | The thumbprint of the client certificate. | +| [`isAdmin`](#parameter-clientcertificatethumbprintsisadmin) | bool | Indicates if the client certificate has admin access to the cluster. Non admin clients can perform only read only operations on the cluster. | + +### Parameter: `clientCertificateThumbprints.certificateThumbprint` + +The thumbprint of the client certificate. + +- Required: Yes +- Type: string + +### Parameter: `clientCertificateThumbprints.isAdmin` + +Indicates if the client certificate has admin access to the cluster. Non admin clients can perform only read only operations on the cluster. + +- Required: Yes +- Type: bool ### Parameter: `clusterCodeVersion` diff --git a/avm/res/service-fabric/cluster/main.bicep b/avm/res/service-fabric/cluster/main.bicep index d2bcd4e614..410b8befa3 100644 --- a/avm/res/service-fabric/cluster/main.bicep +++ b/avm/res/service-fabric/cluster/main.bicep @@ -29,17 +29,17 @@ param maxUnusedVersionsToKeep int = 3 @description('Optional. The settings to enable AAD authentication on the cluster.') param azureActiveDirectory object = {} -@description('Optional. Describes the certificate details like thumbprint of the primary certificate, thumbprint of the secondary certificate and the local certificate store location.') -param certificate object = {} +@description('Conditional. The certificate to use for securing the cluster. The certificate provided will be used for node to node security within the cluster, SSL certificate for cluster management endpoint and default admin client. Required if the certificateCommonNames parameter is not used.') +param certificate certificateType -@description('Optional. Describes a list of server certificates referenced by common name that are used to secure the cluster.') -param certificateCommonNames object = {} +@description('Conditional. Describes a list of server certificates referenced by common name that are used to secure the cluster. Required if the certificate parameter is not used.') +param certificateCommonNames certificateCommonNameType -@description('Optional. The list of client certificates referenced by common name that are allowed to manage the cluster.') -param clientCertificateCommonNames array = [] +@description('Optional. The list of client certificates referenced by common name that are allowed to manage the cluster. Cannot be used if the clientCertificateThumbprints parameter is used.') +param clientCertificateCommonNames clientCertificateCommonNameType -@description('Optional. The list of client certificates referenced by thumbprint that are allowed to manage the cluster.') -param clientCertificateThumbprints array = [] +@description('Optional. The list of client certificates referenced by thumbprint that are allowed to manage the cluster. Cannot be used if the clientCertificateCommonNames parameter is used.') +param clientCertificateThumbprints clientCertificateThumbprintType @description('Optional. The Service Fabric runtime version of the cluster. This property can only by set the user when upgradeMode is set to "Manual". To get list of available Service Fabric versions for new clusters use ClusterVersion API. To get the list of available version for existing clusters use availableClusterVersions.') param clusterCodeVersion string? @@ -135,23 +135,17 @@ param applicationTypes array = [] param enableTelemetry bool = true var clientCertificateCommonNamesVar = [ - for clientCertificateCommonName in clientCertificateCommonNames: { - certificateCommonName: contains(clientCertificateCommonName, 'certificateCommonName') - ? clientCertificateCommonName.certificateCommonName - : null - certificateIssuerThumbprint: contains(clientCertificateCommonName, 'certificateIssuerThumbprint') - ? clientCertificateCommonName.certificateIssuerThumbprint - : null - isAdmin: contains(clientCertificateCommonName, 'isAdmin') ? clientCertificateCommonName.isAdmin : false + for (clientCertificateCommonName, index) in (clientCertificateCommonNames ?? []): { + certificateCommonName: clientCertificateCommonName.certificateCommonName + certificateIssuerThumbprint: clientCertificateCommonName.certificateIssuerThumbprint + isAdmin: clientCertificateCommonName.isAdmin } ] var clientCertificateThumbprintsVar = [ - for clientCertificateThumbprint in clientCertificateThumbprints: { - certificateThumbprint: contains(clientCertificateThumbprint, 'certificateThumbprint') - ? clientCertificateThumbprint.certificateThumbprint - : null - isAdmin: contains(clientCertificateThumbprint, 'isAdmin') ? clientCertificateThumbprint.isAdmin : false + for (clientCertificateThumbprint, index) in (clientCertificateThumbprints ?? []): { + certificateThumbprint: clientCertificateThumbprint.certificateThumbprint + isAdmin: clientCertificateThumbprint.isAdmin } ] @@ -262,24 +256,23 @@ var builtInRoleNames = { ) } -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = - if (enableTelemetry) { - name: '46d3xbcp.res.servicefabric-cluster.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' - } +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.servicefabric-cluster.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' } } } } +} // Service Fabric cluster resource resource serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' = { @@ -304,21 +297,19 @@ resource serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' = { : null certificate: !empty(certificate) ? { - thumbprint: contains(certificate, 'thumbprint') ? certificate.thumbprint : null - thumbprintSecondary: contains(certificate, 'thumbprintSecondary') ? certificate.thumbprintSecondary : null - x509StoreName: contains(certificate, 'x509StoreName') ? certificate.x509StoreName : null + thumbprint: certificate.?thumbprint ?? '' + thumbprintSecondary: certificate.?thumbprintSecondary ?? null + x509StoreName: certificate.?x509StoreName ?? null } : null certificateCommonNames: !empty(certificateCommonNames) ? { - commonNames: contains(certificateCommonNames, 'commonNames') ? certificateCommonNames.commonNames : null - x509StoreName: contains(certificateCommonNames, 'certificateCommonNamesx509StoreName') - ? certificateCommonNames.certificateCommonNamesx509StoreName - : null + commonNames: certificateCommonNames.?commonNames ?? [] + x509StoreName: certificateCommonNames.?x509StoreName ?? null } : null - clientCertificateCommonNames: !empty(clientCertificateCommonNames) ? clientCertificateCommonNamesVar : null - clientCertificateThumbprints: !empty(clientCertificateThumbprints) ? clientCertificateThumbprintsVar : null + clientCertificateCommonNames: clientCertificateCommonNamesVar + clientCertificateThumbprints: clientCertificateThumbprintsVar clusterCodeVersion: clusterCodeVersion diagnosticsStorageAccountConfig: !empty(diagnosticsStorageAccountConfig) ? { @@ -383,17 +374,16 @@ resource serviceFabricCluster 'Microsoft.ServiceFabric/clusters@2021-06-01' = { } // Service Fabric cluster resource lock -resource serviceFabricCluster_lock 'Microsoft.Authorization/locks@2020-05-01' = - if (!empty(lock ?? {}) && lock.?kind != 'None') { - name: lock.?name ?? 'lock-${name}' - properties: { - level: lock.?kind ?? '' - notes: lock.?kind == 'CanNotDelete' - ? 'Cannot delete resource or child resources.' - : 'Cannot delete or modify the resource or child resources.' - } - scope: serviceFabricCluster +resource serviceFabricCluster_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' + ? 'Cannot delete resource or child resources.' + : 'Cannot delete or modify the resource or child resources.' } + scope: serviceFabricCluster +} // Service Fabric cluster RBAC assignment resource serviceFabricCluster_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ @@ -447,6 +437,68 @@ output location string = serviceFabricCluster.location // Definitions // // =============== // +type certificateType = { + @description('Required. The thumbprint of the primary certificate.') + thumbprint: string + + @description('Optional. The thumbprint of the secondary certificate.') + thumbprintSecondary: string? + + @description('Optional. The local certificate store location.') + x509StoreName: ( + | 'AddressBook' + | 'AuthRoot' + | 'CertificateAuthority' + | 'Disallowed' + | 'My' + | 'Root' + | 'TrustedPeople' + | 'TrustedPublisher')? +}? + +type certificateCommonNameType = { + @description('Required. The list of server certificates referenced by common name that are used to secure the cluster.') + commonNames: serverCertificateCommonNameType + + @description('Optional. The local certificate store location.') + x509StoreName: ( + | 'AddressBook' + | 'AuthRoot' + | 'CertificateAuthority' + | 'Disallowed' + | 'My' + | 'Root' + | 'TrustedPeople' + | 'TrustedPublisher')? +}? + +type serverCertificateCommonNameType = { + @description('Required. The common name of the server certificate.') + certificateCommonName: string + + @description('Required. The issuer thumbprint of the server certificate.') + certificateIssuerThumbprint: string +}[] + +type clientCertificateCommonNameType = { + @description('Required. The common name of the client certificate.') + certificateCommonName: string + + @description('Required. The issuer thumbprint of the client certificate.') + certificateIssuerThumbprint: string + + @description('Required. Indicates if the client certificate has admin access to the cluster. Non admin clients can perform only read only operations on the cluster.') + isAdmin: bool +}[]? + +type clientCertificateThumbprintType = { + @description('Required. The thumbprint of the client certificate.') + certificateThumbprint: string + + @description('Required. Indicates if the client certificate has admin access to the cluster. Non admin clients can perform only read only operations on the cluster.') + isAdmin: bool +}[]? + type lockType = { @description('Optional. Specify the name of lock.') name: string? diff --git a/avm/res/service-fabric/cluster/main.json b/avm/res/service-fabric/cluster/main.json index 07ec9d6764..9eeb38d086 100644 --- a/avm/res/service-fabric/cluster/main.json +++ b/avm/res/service-fabric/cluster/main.json @@ -5,14 +5,147 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "2708589601167951653" + "version": "0.28.1.47646", + "templateHash": "16663156727449762885" }, "name": "Service Fabric Clusters", "description": "This module deploys a Service Fabric Cluster.", "owner": "Azure/module-maintainers" }, "definitions": { + "certificateType": { + "type": "object", + "properties": { + "thumbprint": { + "type": "string", + "metadata": { + "description": "Required. The thumbprint of the primary certificate." + } + }, + "thumbprintSecondary": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The thumbprint of the secondary certificate." + } + }, + "x509StoreName": { + "type": "string", + "allowedValues": [ + "AddressBook", + "AuthRoot", + "CertificateAuthority", + "Disallowed", + "My", + "Root", + "TrustedPeople", + "TrustedPublisher" + ], + "nullable": true, + "metadata": { + "description": "Optional. The local certificate store location." + } + } + }, + "nullable": true + }, + "certificateCommonNameType": { + "type": "object", + "properties": { + "commonNames": { + "$ref": "#/definitions/serverCertificateCommonNameType", + "metadata": { + "description": "Required. The list of server certificates referenced by common name that are used to secure the cluster." + } + }, + "x509StoreName": { + "type": "string", + "allowedValues": [ + "AddressBook", + "AuthRoot", + "CertificateAuthority", + "Disallowed", + "My", + "Root", + "TrustedPeople", + "TrustedPublisher" + ], + "nullable": true, + "metadata": { + "description": "Optional. The local certificate store location." + } + } + }, + "nullable": true + }, + "serverCertificateCommonNameType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "certificateCommonName": { + "type": "string", + "metadata": { + "description": "Required. The common name of the server certificate." + } + }, + "certificateIssuerThumbprint": { + "type": "string", + "metadata": { + "description": "Required. The issuer thumbprint of the server certificate." + } + } + } + } + }, + "clientCertificateCommonNameType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "certificateCommonName": { + "type": "string", + "metadata": { + "description": "Required. The common name of the client certificate." + } + }, + "certificateIssuerThumbprint": { + "type": "string", + "metadata": { + "description": "Required. The issuer thumbprint of the client certificate." + } + }, + "isAdmin": { + "type": "bool", + "metadata": { + "description": "Required. Indicates if the client certificate has admin access to the cluster. Non admin clients can perform only read only operations on the cluster." + } + } + } + }, + "nullable": true + }, + "clientCertificateThumbprintType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "certificateThumbprint": { + "type": "string", + "metadata": { + "description": "Required. The thumbprint of the client certificate." + } + }, + "isAdmin": { + "type": "bool", + "metadata": { + "description": "Required. Indicates if the client certificate has admin access to the cluster. Non admin clients can perform only read only operations on the cluster." + } + } + } + }, + "nullable": true + }, "lockType": { "type": "object", "properties": { @@ -160,31 +293,27 @@ } }, "certificate": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/certificateType", "metadata": { - "description": "Optional. Describes the certificate details like thumbprint of the primary certificate, thumbprint of the secondary certificate and the local certificate store location." + "description": "Conditional. The certificate to use for securing the cluster. The certificate provided will be used for node to node security within the cluster, SSL certificate for cluster management endpoint and default admin client. Required if the certificateCommonNames parameter is not used." } }, "certificateCommonNames": { - "type": "object", - "defaultValue": {}, + "$ref": "#/definitions/certificateCommonNameType", "metadata": { - "description": "Optional. Describes a list of server certificates referenced by common name that are used to secure the cluster." + "description": "Conditional. Describes a list of server certificates referenced by common name that are used to secure the cluster. Required if the certificate parameter is not used." } }, "clientCertificateCommonNames": { - "type": "array", - "defaultValue": [], + "$ref": "#/definitions/clientCertificateCommonNameType", "metadata": { - "description": "Optional. The list of client certificates referenced by common name that are allowed to manage the cluster." + "description": "Optional. The list of client certificates referenced by common name that are allowed to manage the cluster. Cannot be used if the clientCertificateThumbprints parameter is used." } }, "clientCertificateThumbprints": { - "type": "array", - "defaultValue": [], + "$ref": "#/definitions/clientCertificateThumbprintType", "metadata": { - "description": "Optional. The list of client certificates referenced by thumbprint that are allowed to manage the cluster." + "description": "Optional. The list of client certificates referenced by thumbprint that are allowed to manage the cluster. Cannot be used if the clientCertificateCommonNames parameter is used." } }, "clusterCodeVersion": { @@ -373,19 +502,19 @@ "copy": [ { "name": "clientCertificateCommonNamesVar", - "count": "[length(parameters('clientCertificateCommonNames'))]", + "count": "[length(coalesce(parameters('clientCertificateCommonNames'), createArray()))]", "input": { - "certificateCommonName": "[if(contains(parameters('clientCertificateCommonNames')[copyIndex('clientCertificateCommonNamesVar')], 'certificateCommonName'), parameters('clientCertificateCommonNames')[copyIndex('clientCertificateCommonNamesVar')].certificateCommonName, null())]", - "certificateIssuerThumbprint": "[if(contains(parameters('clientCertificateCommonNames')[copyIndex('clientCertificateCommonNamesVar')], 'certificateIssuerThumbprint'), parameters('clientCertificateCommonNames')[copyIndex('clientCertificateCommonNamesVar')].certificateIssuerThumbprint, null())]", - "isAdmin": "[if(contains(parameters('clientCertificateCommonNames')[copyIndex('clientCertificateCommonNamesVar')], 'isAdmin'), parameters('clientCertificateCommonNames')[copyIndex('clientCertificateCommonNamesVar')].isAdmin, false())]" + "certificateCommonName": "[coalesce(parameters('clientCertificateCommonNames'), createArray())[copyIndex('clientCertificateCommonNamesVar')].certificateCommonName]", + "certificateIssuerThumbprint": "[coalesce(parameters('clientCertificateCommonNames'), createArray())[copyIndex('clientCertificateCommonNamesVar')].certificateIssuerThumbprint]", + "isAdmin": "[coalesce(parameters('clientCertificateCommonNames'), createArray())[copyIndex('clientCertificateCommonNamesVar')].isAdmin]" } }, { "name": "clientCertificateThumbprintsVar", - "count": "[length(parameters('clientCertificateThumbprints'))]", + "count": "[length(coalesce(parameters('clientCertificateThumbprints'), createArray()))]", "input": { - "certificateThumbprint": "[if(contains(parameters('clientCertificateThumbprints')[copyIndex('clientCertificateThumbprintsVar')], 'certificateThumbprint'), parameters('clientCertificateThumbprints')[copyIndex('clientCertificateThumbprintsVar')].certificateThumbprint, null())]", - "isAdmin": "[if(contains(parameters('clientCertificateThumbprints')[copyIndex('clientCertificateThumbprintsVar')], 'isAdmin'), parameters('clientCertificateThumbprints')[copyIndex('clientCertificateThumbprintsVar')].isAdmin, false())]" + "certificateThumbprint": "[coalesce(parameters('clientCertificateThumbprints'), createArray())[copyIndex('clientCertificateThumbprintsVar')].certificateThumbprint]", + "isAdmin": "[coalesce(parameters('clientCertificateThumbprints'), createArray())[copyIndex('clientCertificateThumbprintsVar')].isAdmin]" } }, { @@ -468,10 +597,10 @@ "maxUnusedVersionsToKeep": "[parameters('maxUnusedVersionsToKeep')]" }, "azureActiveDirectory": "[if(not(empty(parameters('azureActiveDirectory'))), createObject('clientApplication', if(contains(parameters('azureActiveDirectory'), 'clientApplication'), parameters('azureActiveDirectory').clientApplication, null()), 'clusterApplication', if(contains(parameters('azureActiveDirectory'), 'clusterApplication'), parameters('azureActiveDirectory').clusterApplication, null()), 'tenantId', if(contains(parameters('azureActiveDirectory'), 'tenantId'), parameters('azureActiveDirectory').tenantId, null())), null())]", - "certificate": "[if(not(empty(parameters('certificate'))), createObject('thumbprint', if(contains(parameters('certificate'), 'thumbprint'), parameters('certificate').thumbprint, null()), 'thumbprintSecondary', if(contains(parameters('certificate'), 'thumbprintSecondary'), parameters('certificate').thumbprintSecondary, null()), 'x509StoreName', if(contains(parameters('certificate'), 'x509StoreName'), parameters('certificate').x509StoreName, null())), null())]", - "certificateCommonNames": "[if(not(empty(parameters('certificateCommonNames'))), createObject('commonNames', if(contains(parameters('certificateCommonNames'), 'commonNames'), parameters('certificateCommonNames').commonNames, null()), 'x509StoreName', if(contains(parameters('certificateCommonNames'), 'certificateCommonNamesx509StoreName'), parameters('certificateCommonNames').certificateCommonNamesx509StoreName, null())), null())]", - "clientCertificateCommonNames": "[if(not(empty(parameters('clientCertificateCommonNames'))), variables('clientCertificateCommonNamesVar'), null())]", - "clientCertificateThumbprints": "[if(not(empty(parameters('clientCertificateThumbprints'))), variables('clientCertificateThumbprintsVar'), null())]", + "certificate": "[if(not(empty(parameters('certificate'))), createObject('thumbprint', coalesce(tryGet(parameters('certificate'), 'thumbprint'), ''), 'thumbprintSecondary', coalesce(tryGet(parameters('certificate'), 'thumbprintSecondary'), null()), 'x509StoreName', coalesce(tryGet(parameters('certificate'), 'x509StoreName'), null())), null())]", + "certificateCommonNames": "[if(not(empty(parameters('certificateCommonNames'))), createObject('commonNames', coalesce(tryGet(parameters('certificateCommonNames'), 'commonNames'), createArray()), 'x509StoreName', coalesce(tryGet(parameters('certificateCommonNames'), 'x509StoreName'), null())), null())]", + "clientCertificateCommonNames": "[variables('clientCertificateCommonNamesVar')]", + "clientCertificateThumbprints": "[variables('clientCertificateThumbprintsVar')]", "clusterCodeVersion": "[parameters('clusterCodeVersion')]", "diagnosticsStorageAccountConfig": "[if(not(empty(parameters('diagnosticsStorageAccountConfig'))), createObject('blobEndpoint', if(contains(parameters('diagnosticsStorageAccountConfig'), 'blobEndpoint'), parameters('diagnosticsStorageAccountConfig').blobEndpoint, null()), 'protectedAccountKeyName', if(contains(parameters('diagnosticsStorageAccountConfig'), 'protectedAccountKeyName'), parameters('diagnosticsStorageAccountConfig').protectedAccountKeyName, null()), 'protectedAccountKeyName2', if(contains(parameters('diagnosticsStorageAccountConfig'), 'protectedAccountKeyName2'), parameters('diagnosticsStorageAccountConfig').protectedAccountKeyName2, null()), 'queueEndpoint', if(contains(parameters('diagnosticsStorageAccountConfig'), 'queueEndpoint'), parameters('diagnosticsStorageAccountConfig').queueEndpoint, null()), 'storageAccountName', if(contains(parameters('diagnosticsStorageAccountConfig'), 'storageAccountName'), parameters('diagnosticsStorageAccountConfig').storageAccountName, null()), 'tableEndpoint', if(contains(parameters('diagnosticsStorageAccountConfig'), 'tableEndpoint'), parameters('diagnosticsStorageAccountConfig').tableEndpoint, null())), null())]", "eventStoreServiceEnabled": "[parameters('eventStoreServiceEnabled')]", @@ -561,8 +690,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "4241007545422374207" + "version": "0.28.1.47646", + "templateHash": "10847125060034010702" }, "name": "Service Fabric Cluster Application Types", "description": "This module deploys a Service Fabric Cluster Application Type.", diff --git a/avm/res/service-fabric/cluster/tests/e2e/cert/main.test.bicep b/avm/res/service-fabric/cluster/tests/e2e/cert/main.test.bicep deleted file mode 100644 index 3b291fce05..0000000000 --- a/avm/res/service-fabric/cluster/tests/e2e/cert/main.test.bicep +++ /dev/null @@ -1,71 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Certificate' -metadata description = 'This instance deploys the module with a certificate.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-servicefabric.clusters-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param resourceLocation string = deployment().location - -@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'sfccer' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: resourceLocation -} - -// ============== // -// Test Execution // -// ============== // - -@batchSize(1) -module testDeployment '../../../main.bicep' = [ - for iteration in ['init', 'idem']: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - location: resourceLocation - name: '${namePrefix}${serviceShort}001' - managementEndpoint: 'https://${namePrefix}${serviceShort}001.westeurope.cloudapp.azure.com:19080' - reliabilityLevel: 'None' - certificate: { - thumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' - x509StoreName: 'My' - } - nodeTypes: [ - { - applicationPorts: { - endPort: 30000 - startPort: 20000 - } - clientConnectionEndpointPort: 19000 - durabilityLevel: 'Bronze' - ephemeralPorts: { - endPort: 65534 - startPort: 49152 - } - httpGatewayEndpointPort: 19080 - isPrimary: true - name: 'Node01' - } - ] - } - } -] diff --git a/avm/res/service-fabric/cluster/tests/e2e/defaults/main.test.bicep b/avm/res/service-fabric/cluster/tests/e2e/defaults/main.test.bicep index 37e0d4b9c5..25b01ee1f0 100644 --- a/avm/res/service-fabric/cluster/tests/e2e/defaults/main.test.bicep +++ b/avm/res/service-fabric/cluster/tests/e2e/defaults/main.test.bicep @@ -45,6 +45,9 @@ module testDeployment '../../../main.bicep' = [ name: '${namePrefix}${serviceShort}001' managementEndpoint: 'https://${namePrefix}${serviceShort}001.westeurope.cloudapp.azure.com:19080' reliabilityLevel: 'None' + certificate: { + thumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' + } nodeTypes: [ { applicationPorts: { diff --git a/avm/res/service-fabric/cluster/tests/e2e/max/main.test.bicep b/avm/res/service-fabric/cluster/tests/e2e/max/main.test.bicep index 8681e32333..4a496447d9 100644 --- a/avm/res/service-fabric/cluster/tests/e2e/max/main.test.bicep +++ b/avm/res/service-fabric/cluster/tests/e2e/max/main.test.bicep @@ -81,7 +81,7 @@ module testDeployment '../../../main.bicep' = [ certificateIssuerThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' } ] - x509StoreName: '' + x509StoreName: 'My' } clientCertificateCommonNames: [ { @@ -95,16 +95,6 @@ module testDeployment '../../../main.bicep' = [ isAdmin: false } ] - clientCertificateThumbprints: [ - { - certificateThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' - isAdmin: false - } - { - certificateThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC131' - isAdmin: false - } - ] diagnosticsStorageAccountConfig: { blobEndpoint: 'https://${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}/' protectedAccountKeyName: 'StorageAccountKey1' diff --git a/avm/res/service-fabric/cluster/tests/e2e/waf-aligned/main.test.bicep b/avm/res/service-fabric/cluster/tests/e2e/waf-aligned/main.test.bicep index cee548743e..c2a336687b 100644 --- a/avm/res/service-fabric/cluster/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/service-fabric/cluster/tests/e2e/waf-aligned/main.test.bicep @@ -53,6 +53,10 @@ module testDeployment '../../../main.bicep' = [ params: { location: resourceLocation name: '${namePrefix}${serviceShort}001' + certificate: { + thumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' + x509StoreName: 'My' + } tags: { 'hidden-title': 'This is visible in the resource name' resourceType: 'Service Fabric' @@ -70,15 +74,6 @@ module testDeployment '../../../main.bicep' = [ clusterApplication: 'cf33fea8-b30f-424f-ab73-c48d99e0b222' tenantId: tenant().tenantId } - certificateCommonNames: { - commonNames: [ - { - certificateCommonName: 'certcommon' - certificateIssuerThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' - } - ] - x509StoreName: '' - } clientCertificateCommonNames: [ { certificateCommonName: 'clientcommoncert1' @@ -91,16 +86,6 @@ module testDeployment '../../../main.bicep' = [ isAdmin: false } ] - clientCertificateThumbprints: [ - { - certificateThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC130' - isAdmin: false - } - { - certificateThumbprint: '0AC113D5E1D94C401DDEB0EE2B1B96CC131' - isAdmin: false - } - ] diagnosticsStorageAccountConfig: { blobEndpoint: 'https://${nestedDependencies.outputs.storageAccountName}.blob.${environment().suffixes.storage}/' protectedAccountKeyName: 'StorageAccountKey1' diff --git a/avm/res/service-fabric/cluster/version.json b/avm/res/service-fabric/cluster/version.json index 8def869ede..daf1a794d9 100644 --- a/avm/res/service-fabric/cluster/version.json +++ b/avm/res/service-fabric/cluster/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.2", "pathFilters": [ "./main.json" ]