Azure Functions is a serverless computing service provided by Microsoft that allows you to run your code in response to events and triggers without worrying about infrastructure management. In this tutorial, we will go through the steps to implement an Azure Function using Python.
To follow along with this tutorial, you will need the following:
az ad sp create-for-rbac --name terraform --role Contributor --role "Role Based Access Control Administrator" \
--scopes /subscriptions/{your_subscription_id}
Replace {your_subscription_id} with your subscription id
$env:ARM_SUBSCRIPTION_ID = "{your_subscription_id}"
$env:ARM_TENANT_ID = "{tenant_id}"
$env:ARM_CLIENT_ID = "{client_id}"
$env:ARM_CLIENT_SECRET = "{client_secret}"
variables.tf
variable "subscription_id" {
type = string
default = "{your_subscription_id}"
}
variable "resource_group_name" {
type = string
default = "example-rg"
}
variable "resource_group_location" {
type = string
default = "East Asia"
}
variable "tag_environment" {
type = string
default = "dev"
}
variable "example_fw_name" {
type = string
default = "examplefw"
}
variable "function_name" {
type = string
default = "examplefunction"
}
variable "storage_account_name" {
type = string
default = "examplestorage"
}
variable "example_app_service_plan_name" {
type = string
default = "exampleappserviceplan"
}
variable "example_appinsights_plan_name" {
type = string
default = "exampleappinsights"
}
variable "key_vault_name" {
type = string
default = "examplekeyvault"
}
variable "key_vault_secret_name" {
type = string
default = "example-storage-account-connection-string"
}
Replace {your_subscription_id} with your subscription id
main.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=3.84.0"
}
}
}
provider "azurerm" {
features {
key_vault {
purge_soft_deleted_secrets_on_destroy = true
recover_soft_deleted_secrets = true
}
resource_group {
prevent_deletion_if_contains_resources = false
}
}
subscription_id = var.subscription_id
}
resource "azurerm_resource_group" "example" {
name = var.resource_group_name
location = var.resource_group_location
tags = {
environment = var.tag_environment
}
}
resource "random_string" "random" {
length = 10
lower = true
numeric = false
special = false
upper = false
}
resource "azurerm_storage_account" "example" {
name = "${var.storage_account_name}${lower(random_string.random.id)}"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
min_tls_version = "TLS1_2"
}
resource "azurerm_storage_container" "example" {
name = "example"
storage_account_name = azurerm_storage_account.example.name
container_access_type = "blob"
}
resource "azurerm_service_plan" "example" {
name = "${var.example_app_service_plan_name}${lower(random_string.random.id)}"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
os_type = "Linux"
sku_name = "B1"
}
resource "azurerm_application_insights" "example" {
name = "${var.example_appinsights_plan_name}${lower(random_string.random.id)}"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
application_type = "other"
}
resource "azurerm_linux_function_app" "example" {
name = "${var.function_name}${lower(random_string.random.id)}"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
storage_account_name = azurerm_storage_account.example.name
storage_account_access_key = azurerm_storage_account.example.primary_access_key
service_plan_id = azurerm_service_plan.example.id
site_config {
application_insights_key = azurerm_application_insights.example.instrumentation_key
application_insights_connection_string = azurerm_application_insights.example.connection_string
application_stack {
python_version = "3.11"
}
}
identity {
type = "SystemAssigned"
}
}
data "azurerm_client_config" "current" {}
resource "azurerm_key_vault" "example" {
name = "${var.key_vault_name}${lower(random_string.random.id)}"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_retention_days = 7
}
resource "azurerm_key_vault_access_policy" "example" {
key_vault_id = azurerm_key_vault.example.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = data.azurerm_client_config.current.object_id
key_permissions = [
"Create",
"Get",
"List",
]
secret_permissions = [
"Set",
"Get",
"List",
"Delete",
"Purge",
"Recover"
]
}
resource "azurerm_key_vault_access_policy" "example-function" {
key_vault_id = azurerm_key_vault.example.id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = azurerm_linux_function_app.example.identity[0].principal_id
key_permissions = [
"Get",
]
secret_permissions = [
"Get",
]
depends_on = [
azurerm_key_vault_access_policy.example
]
}
resource "azurerm_role_assignment" "example" {
scope = azurerm_key_vault.example.id
role_definition_name = "Reader"
principal_id = azurerm_linux_function_app.example.identity[0].principal_id
depends_on = [
azurerm_key_vault_access_policy.example-function
]
}
resource "azurerm_key_vault_secret" "example" {
name = "${var.key_vault_secret_name}${lower(random_string.random.id)}"
value = azurerm_storage_account.example.primary_connection_string
key_vault_id = azurerm_key_vault.example.id
depends_on = [
azurerm_key_vault_access_policy.example
]
}
import logging
import azure.functions as func
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from azure.storage.blob import BlobServiceClient
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Begin to upload file.')
secret_name = req.params.get('secret_name')
vault_url = req.params.get('vault_url')
logging.info('secret_name: %s' % secret_name)
logging.info('vault_url: %s' % vault_url)
credential = DefaultAzureCredential()
client = SecretClient(vault_url=vault_url, credential=credential)
retrieved_secret = client.get_secret(secret_name)
for input_file in req.files.values():
filename = input_file.filename
logging.info('Filename: %s' % filename)
blob_service_client = BlobServiceClient.from_connection_string(
retrieved_secret.value)
blob_client = blob_service_client.get_blob_client(
container="example", blob=filename)
blob_client.upload_blob(input_file.stream.read(), overwrite=True)
return func.HttpResponse('Upload file to blob storage account successfully.')
Replace {vault_url}, {storage_connection_string} with your config
import logging
import azure.functions as func
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from azure.storage.blob import BlobServiceClient
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Begin to get blob data.')
filename = req.params.get('filename')
secret_name = req.params.get('secret_name')
vault_url = req.params.get('vault_url')
logging.info('filename: %s' % filename)
logging.info('secret_name: %s' % secret_name)
logging.info('vault_url: %s' % vault_url)
credential = DefaultAzureCredential()
client = SecretClient(vault_url=vault_url, credential=credential)
retrieved_secret = client.get_secret(secret_name)
blob_service_client = BlobServiceClient.from_connection_string(
retrieved_secret.value)
blob_client = blob_service_client.get_blob_client(
container="example", blob=filename)
data = blob_client.download_blob().readall()
return func.HttpResponse(data, status_code=200, mimetype="application/octet-stream")
import logging
import azure.functions as func
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from azure.storage.blob import BlobServiceClient
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Begin to get blob data.')
filename = req.params.get('filename')
secret_name = req.params.get('secret_name')
vault_url = req.params.get('vault_url')
logging.info('secret_name: %s' % secret_name)
logging.info('vault_url: %s' % vault_url)
credential = DefaultAzureCredential()
client = SecretClient(vault_url=vault_url, credential=credential)
retrieved_secret = client.get_secret(secret_name)
blob_service_client = BlobServiceClient.from_connection_string(
retrieved_secret.value)
blob_client = blob_service_client.get_blob_client(
container="example", blob=filename)
blob_client.delete_blob()
return func.HttpResponse()
# DO NOT include azure-functions-worker in this file
# The Python Worker is managed by Azure Functions platform
# Manually managing azure-functions-worker may cause unexpected issues
azure-functions
azure-identity
azure-keyvault-secrets
azure-storage-blob
Copyright (c) 2024