title: Bicep Pass storage account connection string to key vault
body: <p>I have 2 resource groups as follow:</p>
  <pre><code>rg-shared
  rg-storage-accounts
  </code></pre>
  <p>in resource group one I am trying to create a storage account and get its connection string and pass it to <code>resourcegroup2</code> on which I have a key vault.</p>
  <p>my actual code is as follow.</p>
  <p>Shared.bicep</p>
  <pre><code>targetScope = 'resourceGroup'
  param deploymentIdOne string = newGuid()
  param deploymentIdTwo string = newGuid()
  output deploymentIdOne string = '${deploymentIdOne}-${deploymentIdTwo}'
  output deploymentIdTwo string = deploymentIdTwo
  
  param keyvaultmain string = 'Name-keyvault'
  param keyvaultshared string = 'Name-keyvault'
  param sharedManagedIdentity string = 'Name-Managed-identity'
  param storageAccountString string
  var storagePrefix = 'sttesteur'
  var clientDataKeyPrefix = 'Key-Data-'
  var learnersguidsecrets = 'Guidtest'
  param tenantCodes array = [
    'tste'
  ]
  
  resource keyVaultClients 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = {
    name: keyvaultmain
  }
  
  resource keyVaultShared 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = {
    name: keyvaultshared
  }
  
  resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
    name: sharedManagedIdentity
    location: resourceGroup().location
  }
  
  resource kvClientsKey 'Microsoft.KeyVault/vaults/keys@2021-06-01-preview' = [for code in tenantCodes: {
    name: '${keyVaultClients.name}/${clientDataKeyPrefix}${toUpper(code)}'
    properties: {
      keySize: 2048
      kty: 'RSA'
      // Assign the least permission
      keyOps: [
        'unwrapKey'
        'wrapKey'
      ]
    }
  }]
  
  resource accessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = {
    name: '${keyVaultClients.name}/add'
    properties: {
      accessPolicies: [
        {
          tenantId: subscription().tenantId
          objectId: managedIdentity.properties.principalId
          permissions: {
            // minimum required permission
            keys: [
              'get'
              'unwrapKey'
              'wrapKey'
            ]
          } 
        }
      ]
    }
  }
  
  resource clientLearnersGuid 'Microsoft.KeyVault/vaults/secrets@2021-06-01-preview' = [for tenant in tenantCodes: {
    name: '${keyVaultClients.name}/${tenant}${learnersguidsecrets}'
    properties: {
      contentType: 'GUID Key'
      value: '${deploymentIdOne}-${deploymentIdTwo}'
    }
  }]
  
  resource storageAccountConnectionString 'Microsoft.KeyVault/vaults/secrets@2021-06-01-preview' = [for tenant in tenantCodes: {
    name: '${keyVaultShared.name}${storagePrefix}${tenant}'
    properties:{
      contentType: '${tenant} Storage Account Connection String'
      value: storageAccountString
    }
  }]
  
  </code></pre>
  <p>And this is my storage-account.bicep</p>
  <pre><code>param tenantCodes array = [
    'tste'
  ]
  
  param tenantManagedIdentity string = 'Manage-identity-Name'
  param secondresource string = 'rg-sec-eur-shared'
  var keyVaultKeyPrefix = 'Key-Data-'
  var storagePrefix = 'sthritesteur'
  
  
  
  
  
  
  // Create a managed identity
  resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
    name: tenantManagedIdentity
    location: resourceGroup().location
  }
  
  
  
  // Create storage accounts
  resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = [for tenantCode in tenantCodes: {
    name: '${storagePrefix}${tenantCode}'
    location: resourceGroup().location
    kind: 'StorageV2'
    sku: {
      name: 'Standard_RAGRS'
    }
    // Assign the identity
    identity: {
      type: 'UserAssigned'
      userAssignedIdentities: {
        '${managedIdentity.id}': {}
      }
    }
    properties: {
      allowCrossTenantReplication: true
      minimumTlsVersion: 'TLS1_2'
      allowBlobPublicAccess: false
      allowSharedKeyAccess: true
      networkAcls: {
        bypass: 'AzureServices'
        virtualNetworkRules: []
        ipRules: []
        defaultAction: 'Allow'
      }
      supportsHttpsTrafficOnly: true
      encryption: {
        identity: {
          // specify which identity to use
          userAssignedIdentity: managedIdentity.id
        }
        keySource: 'Microsoft.Keyvault'
        keyvaultproperties: {
          keyname: '${keyVaultKeyPrefix}${toUpper(tenantCode)}'
          // keyvaulturi: keyVault.properties.vaultUri
          keyvaulturi:'https://keyvaultclient.vault.azure.net'
        }
        services: {
          file: {
            keyType: 'Account'
            enabled: true
          }
          blob: {
            keyType: 'Account'
            enabled: true
          }
        }
      }
      accessTier: 'Hot'
    }
  
  }]
  
  resource storage_Accounts_name_default 'Microsoft.Storage/storageAccounts/blobServices@2021-04-01' = [ for (storageName, i) in tenantCodes :{
    parent: storageAccount[i]
    name: 'default'
    properties: {
      changeFeed: {
        enabled: false
      }
      restorePolicy: {
        enabled: false
      }
      containerDeleteRetentionPolicy: {
        enabled: true
        days: 7
      }
      cors: {
        corsRules: []
      }
      deleteRetentionPolicy: {
        enabled: true
        days: 30
      }
      isVersioningEnabled: true
    }
  }]
  
  module connectionString 'shared.bicep' = [for (storageName, i) in tenantCodes :{
    scope: resourceGroup(secondresource)
    name: storageName
    params: {
      storageAccountString: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount[i].name};AccountKey=${listKeys(storageAccount[i].id, storageAccount[i].apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}'
    }
  }]
  </code></pre>
  <p>This is the details of this workflow.</p>
  <p>in the resource group <code>rg-shared</code>i have 2 key vaults, <code>keyvault-shared</code>and <code>keyvaultstorage</code>. And their purpose is as follow:</p>
  <pre><code>keyvault-shared =&gt; Store StorageAccount Connection String as Secret
  
  keyvault-storage =&gt; Generate a Key Name based on the `tenantCode` in the key section, and in secret, generate a GUID and store it
  </code></pre>
  <p>while in the other resource-group <code>rg-storage</code> I want to create a storage account, encrypt the storage account with the key I have generated in the keyault earlier, and pass the connection string of this storageAccount to the <code>shared</code> key vault.</p>
  <p>Following your advice, I used the module from shared.bicep and called it in my storage account.bicep.</p>
  <p>Based on my command:</p>
  <pre><code>az deployment group what-if -f ./storage-account.bicep -g rg-storage-accounts     
  </code></pre>
  <p>the output It shows that will create only the resource in the storage-account.bicep:</p>
  <ul>
  <li>user identity</li>
  <li>storageAccount</li>
  <li>container</li>
  </ul>
  <p>How to reproduce:</p>
  <ul>
  <li>Create 2 resource groups (shared and storage accounts)</li>
  <li>in Shared create 2 key vaults</li>
  <li>Update the bicep files with the correct key vault names.</li>
  <li>In both bicep scripts in <code>tenantCode</code> put a random name to create a storage account or multiple storage accounts.</li>
  <li>and run the above bicep command.</li>
  </ul>
  <p>I tried to explain as clear as I could this issue, as its driving me crazy and have no idea what I am doing wrong and this stage.</p>
  <p>Please please, if you need anymore information about this issue, just ask and will be glad to clarify any doubt</p>
  <p>UPDATE:
  To generate the key before hand, I moved the key creation into the storage.bicep as follow:</p>
  <pre><code>resource keyVaultClients 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = {
    name: keyvaultmain
    scope: resourceGroup(secondresource)
  }
  
  resource kvClientsKey 'Microsoft.KeyVault/vaults/keys@2021-06-01-preview' = [for code in tenantCodes: {
    name: '${keyVaultClients.name}-${clientDataKeyPrefix}${toUpper(code)}'
    properties: {
      keySize: 2048
      kty: 'RSA'
      // Assign the least permission
      keyOps: [
        'unwrapKey'
        'wrapKey'
      ]
    }
  }]
  </code></pre>
  <p>but I get this error:</p>
  <pre><code>{&quot;error&quot;:{&quot;code&quot;:&quot;InvalidTemplate&quot;,&quot;message&quot;:&quot;Deployment template validation failed: 'The template resource 'keyvault-Key-Data-ORNX' for type 'Microsoft.KeyVault/vaults/keys' at line '54' and column '46' has incorrect segment lengths. A nested resource type must have identical number of segments as its resource name. A root resource type must have segment length one greater than its resource name. Please see https://aka.ms/arm-template/#resources for usage details.'.&quot;,&quot;additionalInfo&quot;:[{&quot;type&quot;:&quot;TemplateViolation&quot;,&quot;info&quot;:{&quot;lineNumber&quot;:54,&quot;linePosition&quot;:46,&quot;path&quot;:&quot;properties.template.resources[1].type&quot;}}]}}
  
  </code></pre>
  <p>Which I don't understand exactly to what refers.</p>
  <p>UPDATE:
  This is an interesting output. So according to the last update (and thank you so so much for your help) I realised that at the code is creating all the correct resource, but at the very end it throws this error:</p>
  <pre><code>{&quot;status&quot;:&quot;Failed&quot;,&quot;error&quot;:{&quot;code&quot;:&quot;DeploymentFailed&quot;,&quot;message&quot;:&quot;At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.&quot;,&quot;details&quot;:[{&quot;code&quot;:&quot;Conflict&quot;,&quot;message&quot;:&quot;{\r\n  \&quot;status\&quot;: \&quot;Failed\&quot;,\r\n  \&quot;error\&quot;: {\r\n    \&quot;code\&quot;: \&quot;ResourceDeploymentFailure\&quot;,\r\n    \&quot;message\&quot;: \&quot;The resource operation completed with terminal provisioning state 'Failed'.\&quot;,\r\n    \&quot;details\&quot;: [\r\n      {\r\n        \&quot;code\&quot;: \&quot;DeploymentFailed\&quot;,\r\n        \&quot;message\&quot;: \&quot;At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.\&quot;,\r\n        \&quot;details\&quot;: [\r\n          {\r\n            \&quot;code\&quot;: \&quot;Conflict\&quot;,\r\n            \&quot;message\&quot;: \&quot;{\\r\\n  \\\&quot;error\\\&quot;: {\\r\\n    \\\&quot;code\\\&quot;: \\\&quot;StorageAccountOperationInProgress\\\&quot;,\\r\\n    \\\&quot;message\\\&quot;: \\\&quot;An operation is currently performing on this storage account that requires exclusive access.\\\&quot;\\r\\n  }\\r\\n}\&quot;\r\n          },\r\n          {\r\n            \&quot;code\&quot;: \&quot;Conflict\&quot;,\r\n            \&quot;message\&quot;: \&quot;{\\r\\n  \\\&quot;error\\\&quot;: {\\r\\n    \\\&quot;code\\\&quot;: \\\&quot;StorageAccountOperationInProgress\\\&quot;,\\r\\n    \\\&quot;message\\\&quot;: \\\&quot;An operation is currently performing on this storage account that requires exclusive access.\\\&quot;\\r\\n  }\\r\\n}\&quot;\r\n          }\r\n        ]\r\n      }\r\n    ]\r\n  }\r\n}&quot;}]}}
  </code></pre>