Build an Azure deployment package through guided choices.
Configure a modern .NET 8 isolated Function workload and generate original Bicep modules, environment files, documentation and a deployment pipeline without copying organization-specific templates.
Local-first Generic names only Bicep-first Feedback encouraged
Original, generic output
GateSift generates from original, neutral templates rather than republishing organization-specific source files. Generated files use generic names and public Azure patterns. Still review your employment and client agreements before publishing work created on company time.
Azure Function workload
gatesift-sample / orders
.NET 8 isolated on Flex Consumption with identity-based runtime connections.
Managed identity Shared-key storage disabled TLS 1.2 minimum RBAC-based access What-if before deployment
infra/main.bicepResource-group orchestration template
targetScope = 'resourceGroup'
@description('Short product or solution name used in resource names.')
@minLength(2)
@maxLength(32)
param projectName string
@description('Short workload name used in resource names.')
@minLength(2)
@maxLength(32)
param workloadName string
@allowed([
'dev'
'test'
'prod'
])
param environment string
@description('Azure region for all resources.')
param location string = resourceGroup().location
@description('Deploy an Azure Service Bus namespace and queue.')
param includeServiceBus bool = true
@description('Queue name when Service Bus is enabled.')
param serviceBusQueueName string = 'messages'
@allowed([
'send'
'receive'
'send-receive'
])
param serviceBusAccess string = 'send-receive'
@description('Deploy an Azure Key Vault using Azure RBAC.')
param includeKeyVault bool = true
@description('Tags applied to generated Azure resources.')
param tags object = {}
var compactProjectName = replace(toLower(projectName), '-', '')
var compactWorkloadName = replace(toLower(workloadName), '-', '')
var uniqueSuffix = take(uniqueString(subscription().id, resourceGroup().id, projectName, workloadName, environment), 6)
var readablePrefix = take(toLower('${projectName}-${workloadName}-${environment}'), 42)
var compactPrefix = take('${compactProjectName}${compactWorkloadName}${environment}', 17)
var generatedFunctionAppName = take('func-${readablePrefix}-${uniqueSuffix}', 60)
var functionPlanName = take('plan-${readablePrefix}-${uniqueSuffix}', 60)
var identityName = take('id-${readablePrefix}-${uniqueSuffix}', 64)
var generatedStorageAccountName = take('st${compactPrefix}${uniqueSuffix}', 24)
var deploymentContainerName = take('app-package-${compactPrefix}', 63)
var logAnalyticsName = take('log-${readablePrefix}-${uniqueSuffix}', 63)
var generatedApplicationInsightsName = take('appi-${readablePrefix}-${uniqueSuffix}', 255)
var generatedServiceBusNamespaceName = take('sbns-${readablePrefix}-${uniqueSuffix}', 50)
var generatedKeyVaultName = take('kv-${compactPrefix}-${uniqueSuffix}', 24)
var commonTags = union(tags, {
environment: environment
workload: workloadName
managedBy: 'GateSift deployment builder'
})
var storageBlobDataOwnerRoleId = 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b'
var storageQueueDataContributorRoleId = '974c5e8b-45b9-4653-ba55-5f855dd0fb88'
var storageTableDataContributorRoleId = '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'
var monitoringMetricsPublisherRoleId = '3913510d-42f4-4e42-8a64-420c390055eb'
var serviceBusDataSenderRoleId = '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39'
var serviceBusDataReceiverRoleId = '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0'
var keyVaultSecretsUserRoleId = '4633458b-17de-408a-b874-0445c86b69e6'
module monitoring './modules/monitoring.bicep' = {
name: 'monitoring-${uniqueSuffix}'
params: {
location: location
logAnalyticsName: logAnalyticsName
applicationInsightsName: generatedApplicationInsightsName
tags: commonTags
}
}
module storage './modules/storage.bicep' = {
name: 'storage-${uniqueSuffix}'
params: {
location: location
storageAccountName: generatedStorageAccountName
deploymentContainerName: deploymentContainerName
tags: commonTags
}
}
resource workloadIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: identityName
location: location
tags: commonTags
}
module serviceBus './modules/service-bus.bicep' = if (includeServiceBus) {
name: 'service-bus-${uniqueSuffix}'
params: {
location: location
namespaceName: generatedServiceBusNamespaceName
queueName: serviceBusQueueName
tags: commonTags
}
}
module keyVault './modules/key-vault.bicep' = if (includeKeyVault) {
name: 'key-vault-${uniqueSuffix}'
params: {
location: location
keyVaultName: generatedKeyVaultName
enablePurgeProtection: environment == 'prod'
tags: commonTags
}
}
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing = {
name: storage.outputs.deployedStorageAccountName
}
resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = {
name: monitoring.outputs.deployedApplicationInsightsName
}
resource storageBlobOwner 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(storageAccount.id, workloadIdentity.id, storageBlobDataOwnerRoleId)
scope: storageAccount
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageBlobDataOwnerRoleId)
principalId: workloadIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
resource storageQueueContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(storageAccount.id, workloadIdentity.id, storageQueueDataContributorRoleId)
scope: storageAccount
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageQueueDataContributorRoleId)
principalId: workloadIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
resource storageTableContributor 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(storageAccount.id, workloadIdentity.id, storageTableDataContributorRoleId)
scope: storageAccount
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageTableDataContributorRoleId)
principalId: workloadIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
resource monitoringPublisher 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(applicationInsights.id, workloadIdentity.id, monitoringMetricsPublisherRoleId)
scope: applicationInsights
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', monitoringMetricsPublisherRoleId)
principalId: workloadIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2024-01-01' existing = if (includeServiceBus) {
name: serviceBus.outputs.deployedNamespaceName
}
resource serviceBusSender 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (includeServiceBus && (serviceBusAccess == 'send' || serviceBusAccess == 'send-receive')) {
name: guid(serviceBusNamespace.id, workloadIdentity.id, serviceBusDataSenderRoleId)
scope: serviceBusNamespace
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', serviceBusDataSenderRoleId)
principalId: workloadIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
resource serviceBusReceiver 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (includeServiceBus && (serviceBusAccess == 'receive' || serviceBusAccess == 'send-receive')) {
name: guid(serviceBusNamespace.id, workloadIdentity.id, serviceBusDataReceiverRoleId)
scope: serviceBusNamespace
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', serviceBusDataReceiverRoleId)
principalId: workloadIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
resource vault 'Microsoft.KeyVault/vaults@2023-07-01' existing = if (includeKeyVault) {
name: keyVault.outputs.deployedKeyVaultName
}
resource keyVaultSecretsUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (includeKeyVault) {
name: guid(vault.id, workloadIdentity.id, keyVaultSecretsUserRoleId)
scope: vault
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', keyVaultSecretsUserRoleId)
principalId: workloadIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
var serviceBusSettings = includeServiceBus ? {
'ServiceBus__fullyQualifiedNamespace': serviceBus.outputs.fullyQualifiedNamespace
'ServiceBus__queueName': serviceBusQueueName
} : {}
var keyVaultSettings = includeKeyVault ? {
'KeyVault__vaultUri': keyVault.outputs.vaultUri
} : {}
module functionApp './modules/function-app-flex.bicep' = {
name: 'function-app-${uniqueSuffix}'
params: {
location: location
functionAppName: generatedFunctionAppName
planName: functionPlanName
identityResourceId: workloadIdentity.id
identityClientId: workloadIdentity.properties.clientId
storageAccountName: storage.outputs.deployedStorageAccountName
deploymentContainerUri: storage.outputs.deploymentContainerUri
applicationInsightsConnectionString: monitoring.outputs.applicationInsightsConnectionString
additionalAppSettings: union(serviceBusSettings, keyVaultSettings)
tags: commonTags
}
dependsOn: [
storageBlobOwner
storageQueueContributor
storageTableContributor
monitoringPublisher
]
}
output functionAppName string = functionApp.outputs.deployedFunctionAppName
output functionAppHostName string = functionApp.outputs.defaultHostName
output managedIdentityName string = workloadIdentity.name
output storageAccountName string = storage.outputs.deployedStorageAccountName
output applicationInsightsName string = monitoring.outputs.deployedApplicationInsightsName
output serviceBusNamespaceName string = includeServiceBus ? serviceBus.outputs.deployedNamespaceName : ''
output keyVaultName string = includeKeyVault ? keyVault.outputs.deployedKeyVaultName : ''
Download the complete deployment packageBicep modules, environment parameters, documentation and the selected pipeline.
Early-access boundary: private endpoints, private DNS, existing landing zones and organization-specific naming rules are not guessed. The generated README explains what still needs deliberate design.