Retrieve storage account access keys from a bicep module
Asked Answered
W

2

18

is it possible to retrieve a Storage Account's Access Key when deploying the Storage Account via a Bicep module?

My parent bicep creates a storage account using a module file, and it then needs an Access Key but I cannot get it working in a way that's secure:

Parent Bicep

module functionAppStorageModule 'storage-account.bicep' = {
  name: 'functionAppStorage'
  params: {
    ...
  }
}

resource functionApp 'Microsoft.Web/sites@2021-03-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    siteConfig: {
      appSettings: [
        {
          name: 'store_key'
          value: ???
        }
      ]
    }
  }
}

I can get it working if I set an output on the module file, and use that output in the parent bicep:

Module Bicep

output storageAccountStr string = 'AccountKey=${listKeys(storageAccount.id, storageAccount.apiVersion).keys[0].value}'

Parent Bicep

properties: {
        siteConfig: {
          appSettings: [
            {
              name: 'store_key'
              value: functionAppStorageModule.outputs.storageAccountStr 
            }
          ]
        }
      }

But this does not seem secure to me as the key appears in plain text in Deployments' Output section on the Azure portal.

Alternatively, I may work around by deploying the storage account beforehand without the use of a module file, as the use of modules seems to be the issue, but just would like to know what I'm trying above is impossible?

Thanks

Woods answered 2/8, 2022 at 16:51 Comment(2)
I was able to reference the storage key in the original bicep: bicep connectionStrings: [ { name: 'AzureBlobStorageConnectionString' connectionString: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=${environment().suffixes.storage}' type: 'Custom' }] Petula
it would be great if what you were trying to do was indeed possible. IMHO it is a much more elegant way to create a function as a resource with all the other resources required (app service plan, storage etc) as a module from within the function.bicep, AND NOT having to create storage for function beforehand (from main.bicep)Pedraza
S
27

If you create the function app in a different module, this should work.

storage-account.bicep file:

param storageAccountName string
...

// Create the storage account
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = {
  name: storageAccountName
  ...
}

// return the name
output name string = storageAccount.name

function-app.bicep file:

...
param storageAccountName string 

// Get a reference to the existing storage
resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' existing = {
  name: storageAccountName
}

// Create the function app
resource functionApp 'Microsoft.Web/sites@2021-03-01' = {
  ...
  properties: {
    siteConfig: {
      appSettings: [
        {
          name: 'store_key'
          // Here we can securely get the access key
          value: 'AccountKey=${storageAccount.listKeys().keys[0].value}'
        }
      ]
    }
  }
}

Then in your main.bicep:

// Create the storage account
module storage 'storage-account.bicep' = {
  name: 'functionAppStorage'
  params: {
    storageAccountName: storageAccountName
    ...
  }
}

// create the function app once the storage has been created
module functionApp 'function-app.bicep' = {
  name: 'functionApp'
  params: {
    ...
    // depends on storage module
    storageAccountName: storage.outputs.name
  }
}

Stupefacient answered 3/8, 2022 at 7:6 Comment(1)
Huh. Thanks! I had somehow never noted that list* functions existed separately, and have been trying to work out how to call resource.list* functions outside the module like OP.Canada
F
0

I found the answer. Here's an example of how to rewrite the external listKeys() call to use a helper function from the resource.

Old:

AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${res_functionStorage.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(res_functionStorage.id, res_functionStorage.apiVersion).keys[0].value}'

New:

AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${res_functionStorage.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${res_functionStorage.listKeys().keys[0].value}'
Fadden answered 28/3, 2023 at 17:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.