Advanced

Securing Azure Functions Solutions

Managed identities, RBAC, HTTP endpoint protection, Entra ID/OAuth2, networking and Key Vault.

Scenario: Globomantics is a cloud solution delivery company facing a lack of knowledge on securely configuring Azure Functions. Joe, a principal engineer, organized comprehensive training to strengthen the security posture of all Azure Functions solutions.

Table of Contents

  1. Azure Functions Security Fundamentals
  2. Managed Identities and RBAC
  3. Securing HTTP Endpoints
  4. Access Keys and Authorization
  5. Microsoft Entra ID and OAuth2
  6. Network and Isolation
  7. Key Vault and Secret Management
  8. TLS, HTTPS and Encryption
  9. Security Monitoring
  10. Complete Security Architecture
  11. Best Practices and Checklist
  12. Glossary

Module 1 – Azure Functions Security Fundamentals {#module-1}

Shared Responsibility Model in Azure Functions

The security of Azure Functions is a shared responsibility between Microsoft Azure and you as developer/architect:

flowchart TD
    subgraph "Microsoft Azure Responsibility"
        M1[Physical infrastructure]
        M2[Hypervisor / VM Isolation]
        M3[Physical network]
        M4[Azure Functions Runtime platform security]
        M5[Host OS patches]
    end
    
    subgraph "Your Responsibility (Developer)"
        D1[Secure application code]
        D2[Authentication and authorization]
        D3[Secret management]
        D4[HTTPS/TLS configuration]
        D5[RBAC access management]
        D6[Security monitoring and intrusion detection]
    end
    
    style D1 fill:#D83B01,color:#fff
    style D2 fill:#D83B01,color:#fff
    style D3 fill:#D83B01,color:#fff

Layered Security Architecture (Defense in Depth)

flowchart TD
    Internet[Internet] --> L1
    
    subgraph L1["Layer 1: Network"]
        WAF[Azure WAF\nDDoS Protection]
        FD[Azure Front Door\nGeo-filtering]
    end
    
    L1 --> L2
    
    subgraph L2["Layer 2: Perimeter"]
        APIM[Azure API Management\nRate limiting, IP filtering]
        NSG[Network Security Groups]
    end
    
    L2 --> L3
    
    subgraph L3["Layer 3: Application"]
        AUTH[Authentication\nEntra ID / EasyAuth]
        KEYS[Function Keys\nAuthorization Levels]
    end
    
    L3 --> L4
    
    subgraph L4["Layer 4: Data"]
        RBAC[RBAC + Managed Identity]
        KV[Azure Key Vault]
        ENC[Encryption at rest\nStorage/SQL/CosmosDB]
    end
    
    style L1 fill:#0078D4,color:#fff
    style L2 fill:#00BCF2,color:#000
    style L3 fill:#68217A,color:#fff
    style L4 fill:#107C10,color:#fff

OWASP Top 10 Applied to Azure Functions

OWASP RiskDescriptionAzure Functions Mitigation
A01: Broken Access ControlUnauthorized resource accessRBAC, Managed Identity, Function Keys
A02: Cryptographic FailuresExposed sensitive dataHTTPS only, TLS 1.2+, Azure Key Vault
A03: InjectionSQL, command injectionParameterized queries, input validation
A05: Security MisconfigurationInsecure default configurationVerified Bicep templates, Azure Policy
A07: Authentication FailuresPoorly implemented authEntra ID, don’t reinvent auth
A09: Security LoggingInsufficient logsApplication Insights, Log Analytics
A10: SSRFServer-Side Request ForgeryValidate URLs, Private Endpoints

Module 2 – Managed Identities and RBAC {#module-2}

What is a Managed Identity?

Managed Identities allow Azure services (like Function Apps) to access other Azure resources without any secrets or connection strings. Azure fully manages the identity and token lifecycle.

Why this is revolutionary:

  • ❌ Before: Server=tcp:sql-server.database.windows.net;Password=S3cur3P@ss!; (exposable secret)
  • ✅ After: The Function App connects via its Azure AD identity — no secret!

Types of Managed Identities

TypeDescriptionLifecycleUse Case
System-AssignedAuto-created for the Function App, tied to itDeleted with the Function AppSimple apps, unique identity
User-AssignedCreated independently, shareablePersists after app deletionShared identity between multiple resources
flowchart LR
    subgraph "System-Assigned Managed Identity"
        FA1[Function App A] -->|has an identity| MSI1[Managed Identity A]
        MSI1 --> AAD1[Microsoft Entra ID]
        MSI1 --> R1[Storage Blob\nData Contributor Role]
        R1 --> Storage1[Azure Storage]
    end
    
    subgraph "User-Assigned Managed Identity"
        UMI[User Managed Identity\n'mi-shared-storage'] --> AAD2[Microsoft Entra ID]
        UMI --> R2[Assigned Role]
        
        FA2[Function App B] --> UMI
        FA3[Function App C] --> UMI
        FA4[Logic App D] --> UMI
        
        R2 --> Storage2[Azure Storage]
    end
    
    style MSI1 fill:#68217A,color:#fff
    style UMI fill:#0078D4,color:#fff

Complete Managed Identity Configuration

Enable via Azure CLI

# Enable System-Assigned Managed Identity
az functionapp identity assign \
  --name func-globomantics-prod \
  --resource-group rg-globomantics

# Get the Principal ID
PRINCIPAL_ID=$(az functionapp identity show \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --query principalId -o tsv)

# Assign required RBAC roles
# 1. Key Vault access (secret reading)
KV_RESOURCE_ID=$(az keyvault show --name kv-globomantics --query id -o tsv)
az role assignment create \
  --assignee $PRINCIPAL_ID \
  --role "Key Vault Secrets User" \
  --scope $KV_RESOURCE_ID

# 2. Storage Blob access (read/write)
STORAGE_RESOURCE_ID=$(az storage account show \
  --name stglobomantics \
  --resource-group rg-globomantics \
  --query id -o tsv)
az role assignment create \
  --assignee $PRINCIPAL_ID \
  --role "Storage Blob Data Contributor" \
  --scope $STORAGE_RESOURCE_ID

# 3. Service Bus access (send/receive)
SB_RESOURCE_ID=$(az servicebus namespace show \
  --name sb-globomantics \
  --resource-group rg-globomantics \
  --query id -o tsv)
az role assignment create \
  --assignee $PRINCIPAL_ID \
  --role "Azure Service Bus Data Owner" \
  --scope $SB_RESOURCE_ID

Enable via Bicep

resource functionApp 'Microsoft.Web/sites@2023-01-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  identity: {
    type: 'SystemAssigned'  // ← Enables Managed Identity
  }
  properties: {
    // ... other properties
  }
}

// Assign Key Vault Secrets User role
resource keyVaultRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(keyVault.id, functionApp.id, 'KeyVaultSecretsUser')
  scope: keyVault
  properties: {
    roleDefinitionId: subscriptionResourceId(
      'Microsoft.Authorization/roleDefinitions',
      '4633458b-17de-408a-b874-0445c86b69e6')  // Key Vault Secrets User
    principalId: functionApp.identity.principalId
    principalType: 'ServicePrincipal'
  }
}

Using DefaultAzureCredential in Code

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Azure.Storage.Blobs;
using Azure.Messaging.ServiceBus;

public class SecureDataService
{
    private readonly SecretClient _secretClient;
    private readonly BlobServiceClient _blobClient;
    private readonly ILogger<SecureDataService> _logger;

    public SecureDataService(ILogger<SecureDataService> logger)
    {
        _logger = logger;
        
        // DefaultAzureCredential automatically uses:
        // 1. In production: System-Assigned Managed Identity
        // 2. Locally: Azure CLI credentials (az login)
        // 3. Fallback: Visual Studio credentials
        var credential = new DefaultAzureCredential();

        // Key Vault: NO connection string with secret!
        _secretClient = new SecretClient(
            new Uri(Environment.GetEnvironmentVariable("KeyVaultUri")!),
            credential);

        // Blob Storage: NO connection string with AccountKey!
        _blobClient = new BlobServiceClient(
            new Uri(Environment.GetEnvironmentVariable("BlobStorageUri")!),
            credential);
    }

    public async Task<string> GetSecretAsync(string secretName)
    {
        var secret = await _secretClient.GetSecretAsync(secretName);
        return secret.Value.Value;
    }
}

Identity-based App Settings

# Configuration without secrets (identity-based connections)
az functionapp config appsettings set \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --settings \
    "KeyVaultUri=https://kv-globomantics.vault.azure.net/" \
    "BlobStorageUri=https://stglobomantics.blob.core.windows.net/" \
    "ServiceBusNamespace=sb-globomantics.servicebus.windows.net" \
    "AzureWebJobsStorage__blobServiceUri=https://stglobomantics.blob.core.windows.net/" \
    "AzureWebJobsStorage__queueServiceUri=https://stglobomantics.queue.core.windows.net/"

Important RBAC Roles for Azure Functions

ServiceRolePermissions
Azure StorageStorage Blob Data ContributorRead, write, delete blobs
Azure StorageStorage Queue Data ContributorRead, send, delete queue messages
Azure Key VaultKey Vault Secrets UserRead secrets (recommended)
Azure Service BusAzure Service Bus Data ReceiverReceive messages
Azure Service BusAzure Service Bus Data SenderSend messages
Azure Cosmos DBCosmos DB Built-in Data ReaderRead documents
Azure SQLdb_datareader / db_datawriterVia SQL CREATE USER ... FROM EXTERNAL PROVIDER

Module 3 – Securing HTTP Endpoints {#module-3}

Azure Functions Access Key Types

flowchart TD
    Request[HTTP Request] --> Validate{Access Key\nValidation}
    Validate -->|Valid code| Function[Execute Function]
    Validate -->|Invalid code| Reject[401 Unauthorized]
    
    subgraph "Key types"
        AnonKey[Anonymous\nNo key required]
        FuncKey[Function Key\nAccess to one function]
        HostKey[Host Key\nAccess to all functions]
        MasterKey[Master Key\nAdmin + runtime API access]
        SystemKey[System Key\nInternal extension usage]
    end
Key TypeScopeRevocableAppropriate Usage
AnonymousNo auth requiredN/AHealth checks, public endpoints
Function KeySingle functionSpecific B2B integrations
Host KeyAll functions in the appMultiple trusted clients
Master KeyAdmin + all functions❌ (immutable)NEVER in production!
System KeyInternal extensionsPartialEvent Grid, Durable Functions
public class SecureEndpoints
{
    // ❌ DANGEROUS for endpoints with sensitive data
    [Function("PublicEndpoint")]
    public HttpResponseData PublicEndpoint(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req)
    {
        // Only use for: health checks, truly public endpoints
        var response = req.CreateResponse(System.Net.HttpStatusCode.OK);
        response.WriteString("Public endpoint");
        return response;
    }

    // ✅ Appropriate for specific service integrations
    [Function("WebhookEndpoint")]
    public async Task<HttpResponseData> WebhookEndpoint(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = "webhooks/payment")] 
        HttpRequestData req)
    {
        // Requires the specific key for this function
        // Ideal for B2B webhooks (Stripe, GitHub, etc.)
        var payload = await req.ReadFromJsonAsync<PaymentWebhookPayload>();
        return req.CreateResponse(System.Net.HttpStatusCode.OK);
    }
}

Secure Key Storage

By default, keys are stored in Azure Blob Storage. For increased security, store them in Azure Key Vault:

# Configure key storage in Key Vault
az functionapp config appsettings set \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --settings "AzureWebJobsSecretStorageType=keyvault" \
             "AzureWebJobsSecretStorageKeyVaultUri=https://kv-globomantics.vault.azure.net/"

Module 4 – Access Keys and Authorization {#module-4}

Passing the Key in the Request

# Option 1: Query string parameter (simple but visible in URL logs)
curl "https://func-globomantics.azurewebsites.net/api/myfunction?code=YOUR_KEY_HERE"

# Option 2: x-functions-key header (recommended - not visible in URL)
curl "https://func-globomantics.azurewebsites.net/api/myfunction" \
  -H "x-functions-key: YOUR_KEY_HERE"

Module 5 – Microsoft Entra ID and OAuth2 {#module-5}

EasyAuth (App Service Authentication)

EasyAuth is the built-in authentication middleware of Azure App Service / Azure Functions. It fully manages OAuth2/OIDC token validation before your code is executed.

sequenceDiagram
    participant Client
    participant EasyAuth as EasyAuth\n(App Service Auth Middleware)
    participant Entra as Microsoft Entra ID
    participant Function as Your Code

    Client->>EasyAuth: HTTP Request\n(without token)
    EasyAuth-->>Client: 401 + Redirect URL to Entra
    Client->>Entra: User authentication
    Entra-->>Client: JWT Token (id_token + access_token)
    Client->>EasyAuth: Request with Bearer Token
    EasyAuth->>Entra: Validate token
    Entra-->>EasyAuth: Token valid
    EasyAuth->>Function: Request + Injected Headers\n(X-MS-CLIENT-PRINCIPAL, etc.)
    Function-->>EasyAuth: Response
    EasyAuth-->>Client: Response

EasyAuth configuration via CLI:

az webapp auth microsoft update \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --client-id "your-app-registration-client-id" \
  --client-secret "your-client-secret" \
  --issuer "https://login.microsoftonline.com/{tenant-id}/v2.0"

az webapp auth update \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --enabled true \
  --action LoginWithAzureActiveDirectory

Reading Identity Information from EasyAuth Headers

[Function("ProfileFunction")]
public HttpResponseData Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req)
{
    string? principalHeader = req.Headers
        .GetValues("x-ms-client-principal")
        ?.FirstOrDefault();

    if (principalHeader == null)
        return req.CreateResponse(HttpStatusCode.Unauthorized);

    byte[] decoded = Convert.FromBase64String(principalHeader);
    var principal = JsonSerializer.Deserialize<ClientPrincipal>(
        Encoding.UTF8.GetString(decoded));

    string userName = req.Headers
        .GetValues("x-ms-client-principal-name")
        ?.FirstOrDefault() ?? "unknown";

    var response = req.CreateResponse(HttpStatusCode.OK);
    await response.WriteStringAsync($"Hello, {userName}!");
    return response;
}

public record ClientPrincipal(
    string auth_type,
    string name_type,
    string role_type,
    List<ClaimRecord> claims);

public record ClaimRecord(string typ, string val);

Module 6 – Network and Isolation {#module-6}

Secure Network Configuration

flowchart TB
    Internet[Internet] --> WAF[Azure WAF / Front Door]
    WAF --> APIM[Azure API Management\nSubnet: snet-apim]
    
    subgraph VNet["Virtual Network: vnet-globomantics"]
        subgraph SnetAPIM["Subnet: snet-apim"]
            APIM
        end
        subgraph SnetFunc["Subnet: snet-functions"]
            FA[Function App\nVNet Integration]
        end
        subgraph SnetData["Subnet: snet-data"]
            SQL["Azure SQL\nPrivate Endpoint"]
            COSMOS["Cosmos DB\nPrivate Endpoint"]
        end
    end
    
    APIM -->|Private Endpoint| FA
    FA -->|Private Endpoint| SQL
    FA -->|Private Endpoint| COSMOS
    
    style FA fill:#68217A,color:#fff
    style WAF fill:#0078D4,color:#fff
# Complete network configuration

# 1. Create the VNet and subnets
az network vnet create \
  --name vnet-globomantics \
  --resource-group rg-globomantics \
  --address-prefix 10.0.0.0/16

az network vnet subnet create \
  --vnet-name vnet-globomantics \
  --resource-group rg-globomantics \
  --name snet-functions \
  --address-prefix 10.0.2.0/24 \
  --delegations Microsoft.Web/serverFarms

# 2. VNet Integration for the Function App (Premium required)
az functionapp vnet-integration add \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --vnet vnet-globomantics \
  --subnet snet-functions

# 3. Restrict inbound access (IP allowlist)
az functionapp config access-restriction add \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --rule-name "AllowAPIMOnly" \
  --action Allow \
  --ip-address "10.0.1.0/24" \
  --priority 100

# 4. Create Private Endpoint for SQL Database
az network private-endpoint create \
  --name pe-sql-globomantics \
  --resource-group rg-globomantics \
  --vnet-name vnet-globomantics \
  --subnet snet-data \
  --private-connection-resource-id $(az sql server show \
    --name sql-globomantics \
    --resource-group rg-globomantics \
    --query id -o tsv) \
  --group-id sqlServer \
  --connection-name "sql-connection"

Module 7 – Key Vault and Secret Management {#module-7}

Key Vault References in App Settings

Key Vault References allow referencing Key Vault secrets directly in App Settings, without ever copying the secret value.

sequenceDiagram
    participant Admin as Administrator
    participant KV as Azure Key Vault
    participant FA as Function App
    participant Code as Your Code

    Admin->>KV: Create secret "sql-connection-string"
    Admin->>FA: Configure App Setting:\n@Microsoft.KeyVault(SecretUri=...)
    
    Note over FA,KV: On Function App startup
    FA->>KV: Request the secret (via Managed Identity)
    KV-->>FA: Secret value
    FA->>Code: Inject as environment variable
    Code-->>FA: Use as normal string
# 1. Create Key Vault and secrets
az keyvault create \
  --name kv-globomantics \
  --resource-group rg-globomantics \
  --location eastus \
  --enable-rbac-authorization true \
  --enable-soft-delete true \
  --soft-delete-retention-days 90

# 2. Add secrets
az keyvault secret set \
  --vault-name kv-globomantics \
  --name "sql-connection-string" \
  --value "Server=tcp:sql-globomantics.database.windows.net;..."

# 3. Configure App Settings with Key Vault references
SQL_SECRET_URI=$(az keyvault secret show \
  --vault-name kv-globomantics \
  --name "sql-connection-string" \
  --query id -o tsv)

az functionapp config appsettings set \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --settings \
    "SqlConnectionString=@Microsoft.KeyVault(SecretUri=$SQL_SECRET_URI)"

Transparent access in code:

// Azure Functions automatically resolves the Key Vault reference
// No Key Vault SDK needed here!
public class PaymentFunction
{
    private readonly string _stripeSecretKey;

    public PaymentFunction()
    {
        _stripeSecretKey = Environment.GetEnvironmentVariable("StripeSecretKey")
            ?? throw new InvalidOperationException("Stripe secret key not configured");
    }
}

Module 8 – TLS, HTTPS and Encryption {#module-8}

HTTPS and TLS Configuration

# Force HTTPS only
az functionapp update \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --set httpsOnly=true

# Configure minimum TLS version (TLS 1.2 minimum)
az functionapp config set \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --min-tls-version 1.2

# Disable FTP (FTPS)
az functionapp config set \
  --name func-globomantics-prod \
  --resource-group rg-globomantics \
  --ftps-state Disabled

Configuration via Bicep:

resource functionApp 'Microsoft.Web/sites@2023-01-01' = {
  properties: {
    httpsOnly: true
    siteConfig: {
      ftpsState: 'Disabled'
      minTlsVersion: '1.2'
      http20Enabled: true
    }
  }
}

Module 9 – Security Monitoring {#module-9}

KQL Queries for Security Audit

// Detect unauthorized access attempts (HTTP 401/403)
requests
| where timestamp > ago(24h)
| where resultCode in ("401", "403")
| summarize Count = count() by bin(timestamp, 1h), name, client_IP
| where Count > 10  // Alert threshold
| order by Count desc

// Audit configuration changes
AzureActivity
| where OperationNameValue contains "Microsoft.Web/sites"
| where ActivityStatusValue == "Success"
| where OperationNameValue contains "write"
| project TimeGenerated, Caller, OperationNameValue, ResourceGroup, Resource
| order by TimeGenerated desc

// Detect connections from unknown IPs
SigninLogs
| where AppDisplayName contains "Globomantics"
| where RiskState != "none"  // Risky connections
| project TimeGenerated, UserPrincipalName, IPAddress, RiskLevelAggregated, Location
| order by TimeGenerated desc

Module 10 – Complete Security Architecture {#module-10}

flowchart TB
    subgraph "Internet"
        Client[External Client]
    end
    
    subgraph "DMZ Zone"
        WAF[Azure WAF\n+ DDoS Protection]
        AFD[Azure Front Door\nGeo-filtering, SSL termination]
    end
    
    subgraph "API Management Zone"
        APIM[Azure API Management\nRate limiting, OAuth2 validation\nIP filtering, Logging]
    end
    
    subgraph "Functions Zone (VNet)"
        FA[Function App\nManaged Identity\nHTTPS only, TLS 1.2+]
    end
    
    subgraph "Data Zone (VNet - Private)"
        SQL["Azure SQL\nPrivate Endpoint\nTDE, Always Encrypted"]
        COSMOS["Cosmos DB\nPrivate Endpoint\nEncryption at rest"]
        KV[Azure Key Vault\nPremium tier\nHSM backed]
    end
    
    subgraph "Cross-cutting Security"
        ENTRA[Microsoft Entra ID\nConditional Access\nMFA]
        ASC[Defender for Cloud\nSecurity recommendations]
        SENT[Microsoft Sentinel\nSIEM, threat detection]
        LOG[Log Analytics\nAudit logs, KQL queries]
    end
    
    Client --> WAF --> AFD --> APIM
    APIM -->|Private Endpoint| FA
    FA -->|Private Endpoint + MSI| SQL
    FA -->|Private Endpoint + MSI| COSMOS
    FA -->|MSI| KV
    
    ENTRA -.->|Authentication| APIM & FA
    ASC -.->|Monitoring| FA & SQL & COSMOS
    LOG -.->|Logs| FA & APIM
    SENT -.->|Analysis| LOG
    
    style FA fill:#68217A,color:#fff
    style KV fill:#FFB900,color:#000
    style ENTRA fill:#0078D4,color:#fff

Module 11 – Best Practices and Checklist {#module-11}

Azure Functions Security Checklist

CategoryCheckPriority
IdentityManaged Identity enabled (System-Assigned minimum)🔴 Critical
IdentityNo connection strings with keys in App Settings🔴 Critical
IdentityIdentity-based connections for Storage, Service Bus, Cosmos DB🔴 Critical
SecretsKey Vault References for all secrets🔴 Critical
SecretsNo secrets in source code or Git commits🔴 Critical
NetworkHTTPS Only enabled🔴 Critical
NetworkTLS 1.2 minimum configured🔴 Critical
NetworkFTP/FTPS disabled🟡 Important
NetworkCORS explicitly configured (not * in prod)🟡 Important
HTTP AuthAuthLevel.Anonymous only for health checks🟡 Important
HTTP AuthMaster Key NEVER used in client applications🔴 Critical
HTTP AuthEasyAuth or APIM for public APIs🟡 Important
Advanced NetworkVNet Integration (Premium plan)🟢 Recommended
Advanced NetworkPrivate Endpoints for data services🟢 Recommended
MonitoringApplication Insights configured🟡 Important
MonitoringAlerts on 401/403 errors🟡 Important
ComplianceDefender for App Service enabled🟡 Important
RBACLeast privilege principle for all roles🔴 Critical

Security Scenario Reference (Globomantics)

Target ServiceSecure Access Method
Azure Key VaultManaged Identity + RBAC role “Key Vault Secrets User”
Storage AccountManaged Identity + RBAC role “Storage Blob Data Contributor”
Azure SQL DatabaseManaged Identity + access via Entra ID (no SQL password)
Public HTTP EndpointsEasyAuth (Entra ID) or APIM with OAuth

Module 7 – Managed Identity: Deep Dive {#module-7-deep-dive}

DefaultAzureCredential: Authentication Chain

DefaultAzureCredential from the Azure.Identity library tries identity sources in this order:

flowchart TD
    A[DefaultAzureCredential] --> B{Environment variable\nAZURE_CLIENT_ID?}
    B -- Yes --> C[EnvironmentCredential\nClient ID + Secret/Cert]
    B -- No --> D{Workload Identity\nin Kubernetes?}
    D -- Yes --> E[WorkloadIdentityCredential]
    D -- No --> F{Managed Identity\navailable?}
    F -- Yes --> G[ManagedIdentityCredential\n✅ Azure Production]
    F -- No --> H{Visual Studio\nconfigured?}
    H -- Yes --> I[VisualStudioCredential\n✅ Local development]
    H -- No --> J{Azure CLI\nconnected?}
    J -- Yes --> K[AzureCliCredential\n✅ Local CLI dev]

Managed Identity for Azure SQL Database

// SQL connection with Managed Identity (no password!)
using Microsoft.Data.SqlClient;

var connectionString = 
    "Server=myserver.database.windows.net;" +
    "Database=mydb;" +
    "Authentication=Active Directory Managed Identity;";

using var connection = new SqlConnection(connectionString);
await connection.OpenAsync();
// Entra ID manages authentication automatically
-- In Azure SQL: create user for the Managed Identity
CREATE USER [myFunctionApp] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [myFunctionApp];
ALTER ROLE db_datawriter ADD MEMBER [myFunctionApp];

Glossary {#glossary}

TermDefinition
APIMAzure API Management - gateway for securing and managing APIs
CORSCross-Origin Resource Sharing - cross-domain request control
DefaultAzureCredentialAzure SDK class that automatically detects available credentials
EasyAuthApp Service Authentication - built-in authentication middleware
Entra IDMicrosoft Entra ID (formerly Azure Active Directory) - identity service
FTPSFTP over SSL - secure transfer protocol (disable if unused)
HSMHardware Security Module - physical chip for storing cryptographic keys
JWTJSON Web Token - standard format for authentication tokens
Key Vault Reference@Microsoft.KeyVault(...) in App Settings - automatic secret resolution
Managed IdentityAzure AD identity automatically managed by Azure for a resource
OAuth 2.0Authorization protocol for APIs
OIDCOpenID Connect - extension of OAuth 2.0 for authentication
OWASPOpen Web Application Security Project - organization defining web risks
Private EndpointPrivate network connection to an Azure service via VNet
RBACRole-Based Access Control - Azure role-based access control
System-Assigned MSIManaged Identity tied to the lifecycle of an Azure resource
TDETransparent Data Encryption - automatic encryption of SQL data at rest
TLSTransport Layer Security - encryption protocol for HTTPS communications
User-Assigned MSIIndependent Managed Identity, shareable between multiple resources
VNetVirtual Network - virtual private network in Azure
VNet IntegrationConnecting a Function App to a VNet to access private resources
WAFWeb Application Firewall - application firewall against web attacks
Zero TrustSecurity model: never trust, always verify

Search Terms

securing · azure · functions · serverless · microsoft · security · managed · identity · app · configuration · access · architecture · authentication · checklist · defaultazurecredential · easyauth · enable · https · identities · network · rbac · secure · settings · tls

Interested in this course?

Contact us to book it or get a custom training plan for your team.