AZ-204 Crash Course: Azure Security
Implementation (Module 3)
Overview
Azure Security represents 15-20% of the AZ-204 exam. This module covers:
Microsoft Entra ID (Azure AD) integration and authentication
Microsoft Identity Platform and Microsoft Graph
Azure Key Vault (secrets, keys, certificates)
Managed Identities and authentication patterns
Role-Based Access Control (RBAC)
Secure configuration and networking
1. Microsoft Entra ID Integration
Core Concepts
Microsoft Entra ID (formerly Azure AD) is Microsoft's cloud-based identity and access
management service that provides:
Single Sign-On (SSO): Seamless access across applications
Multi-Factor Authentication (MFA): Enhanced security
Conditional Access: Risk-based access policies
Application Integration: OAuth 2.0, OpenID Connect, SAML
Authentication Flows
Authorization Code Flow (Recommended for web apps):
sequenceDiagram
participant User
participant App
participant EntraID
participant Resource
User->>App: Access protected resource
App->>EntraID: Redirect to authorization endpoint
EntraID->>User: Present login page
User->>EntraID: Provide credentials
EntraID->>App: Return authorization code
App->>EntraID: Exchange code for tokens
EntraID->>App: Return access token + refresh token
App->>Resource: Access resource with token
Client Credentials Flow (Service-to-service):
public async Task<string> GetAccessTokenAsync()
{
var app = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
.Build();
var result = await app.AcquireTokenForClient(scopes)
.ExecuteAsync();
return result.AccessToken;
}
App Registration Configuration
Required Settings:
Application ID URI: Unique identifier for your application
Redirect URIs: Valid callback URLs after authentication
API Permissions: Delegated and application permissions
Authentication: Platform configurations (Web, SPA, Mobile)
Certificates & Secrets: Client credentials for authentication
Permission Types:
Delegated Permissions: Act on behalf of signed-in user
Application Permissions: Act as the application itself (daemon scenarios)
MSAL Integration
Web Application Example:
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAd");
services.AddMicrosoftGraph(Configuration.GetSection("MicrosoftGraph"));
}
// Controller
[Authorize]
public class HomeController : Controller
{
private readonly GraphServiceClient _graphServiceClient;
public HomeController(GraphServiceClient graphServiceClient)
{
_graphServiceClient = graphServiceClient;
}
public async Task<IActionResult> Profile()
{
var user = await _graphServiceClient.Me.Request().GetAsync();
return View(user);
}
}
Console Application Example:
public class Program
{
static async Task Main(string[] args)
{
var app = PublicClientApplicationBuilder
.Create(clientId)
.WithAuthority(authority)
.WithRedirectUri("http://localhost")
.Build();
var accounts = await app.GetAccountsAsync();
AuthenticationResult result;
try
{
result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
.ExecuteAsync();
}
catch (MsalUiRequiredException)
{
result = await app.AcquireTokenInteractive(scopes)
.ExecuteAsync();
}
Console.WriteLine($"Access token: {result.AccessToken}");
}
}
2. Microsoft Graph Integration
Core Concepts
Microsoft Graph is the unified API endpoint for Microsoft 365, Windows 10, and Enterprise
Mobility + Security data:
Single Endpoint: https://graph.microsoft.com
RESTful API: Standard HTTP methods
SDKs Available: .NET, Java, JavaScript, Python, PHP
Rich Data Model: Users, groups, mail, calendar, files, and more
Graph API Permissions
Common Permission Scopes:
Resource Delegated Application
User Profile User.Read User.Read.All
Mail Mail.Read Mail.Read
Calendar Calendars.Read Calendars.Read
Files Files.Read Files.Read.All
Directory Directory.Read.All Directory.Read.All
SDK Operations
User Operations:
// Get current user
var me = await graphServiceClient.Me.Request().GetAsync();
// Get user by ID
var user = await graphServiceClient.Users["user@domain.com"].Request().GetAsync();
// Get user's manager
var manager = await graphServiceClient.Me.Manager.Request().GetAsync();
// Get user's direct reports
var directReports = await graphServiceClient.Me.DirectReports.Request().GetAsync();
// Update user properties
var userToUpdate = new User
{
DisplayName = "Updated Name",
JobTitle = "Senior Developer"
};
await graphServiceClient.Users[user.Id].Request().UpdateAsync(userToUpdate);
Mail Operations:
// Get messages
var messages = await graphServiceClient.Me.Messages
.Request()
.Top(10)
.OrderBy("receivedDateTime desc")
.GetAsync();
// Send mail
var message = new Message
{
Subject = "Test Email",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = "<h1>Hello from Microsoft Graph!</h1>"
},
ToRecipients = new[]
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "recipient@domain.com",
Name = "Recipient Name"
}
}
}
};
await graphServiceClient.Me.SendMail(message, true).Request().PostAsync();
File Operations:
// List files in OneDrive
var driveItems = await graphServiceClient.Me.Drive.Root.Children
.Request()
.GetAsync();
// Upload file
using var fileStream = System.IO.File.OpenRead("document.pdf");
var uploadedItem = await graphServiceClient.Me.Drive.Root
.ItemWithPath("document.pdf")
.Content
.Request()
.PutAsync<DriveItem>(fileStream);
// Download file
var downloadStream = await graphServiceClient.Me.Drive.Items[uploadedItem.Id]
.Content
.Request()
.GetAsync();
Batch Requests
// Create batch request
var batch = new BatchRequestContent();
// Add requests to batch
var meRequest = graphServiceClient.Me.Request();
var messagesRequest = graphServiceClient.Me.Messages.Request().Top(5);
var meRequestId = batch.AddBatchRequestStep(meRequest);
var messagesRequestId = batch.AddBatchRequestStep(messagesRequest);
// Execute batch
var batchResponse = await graphServiceClient.Batch.Request().PostAsync(batch);
// Get responses
var meResponse = await batchResponse.GetResponseByIdAsync<User>(meRequestId);
var messagesResponse = await batchResponse.GetResponseByIdAsync<ICollectionPage<Message>>
3. Azure Key Vault
Core Concepts
Azure Key Vault is a secure secrets management service that provides:
Secrets: Connection strings, passwords, API keys
Keys: Cryptographic keys for encryption/decryption
Certificates: SSL/TLS certificates with automated renewal
Hardware Security Module (HSM): FIPS 140-2 Level 2 validated
Access Policies vs RBAC
Access Policies (Traditional):
Vault-level permissions
Principal + permissions model
Fine-grained operation control
RBAC (Recommended):
Azure standard role assignments
Inherited from subscription/resource group
Consistent with Azure security model
RBAC Roles:
Role Description
Key Vault Administrator Full access to all Key Vault operations
Key Vault Reader Read metadata of key vaults and certificates/keys/secrets
Key Vault Secrets User Read secret contents
Key Vault Crypto User Encrypt/decrypt using keys
Key Vault Certificate User Read certificate contents
SDK Operations
Secrets Management:
var credential = new DefaultAzureCredential();
var secretClient = new SecretClient(new Uri(keyVaultUrl), credential);
// Set secret
KeyVaultSecret secret = await secretClient.SetSecretAsync("DatabaseConnectionString", con
// Get secret
KeyVaultSecret retrievedSecret = await secretClient.GetSecretAsync("DatabaseConnectionStr
string value = retrievedSecret.Value;
// List secrets
await foreach (SecretProperties secretProperty in secretClient.GetPropertiesOfSecretsAsyn
{
Console.WriteLine($"Secret: {secretProperty.Name}");
}
// Update secret properties
SecretProperties properties = new SecretProperties("DatabaseConnectionString")
{
ExpiresOn = DateTimeOffset.UtcNow.AddYears(1)
};
await secretClient.UpdateSecretPropertiesAsync(properties);
// Delete secret
DeletedSecret deletedSecret = await secretClient.StartDeleteSecretAsync("DatabaseConnecti
Key Management:
var keyClient = new KeyClient(new Uri(keyVaultUrl), credential);
// Create key
CreateKeyOptions keyOptions = new CreateKeyOptions("MyEncryptionKey", KeyType.Rsa)
{
KeySize = 2048,
ExpiresOn = DateTimeOffset.UtcNow.AddYears(2)
};
KeyVaultKey key = await keyClient.CreateKeyAsync(keyOptions);
// Encrypt data
var cryptoClient = keyClient.GetCryptographyClient(key.Name);
byte[] data = Encoding.UTF8.GetBytes("Sensitive data to encrypt");
EncryptResult encryptResult = await cryptoClient.EncryptAsync(EncryptionAlgorithm.RsaOaep
// Decrypt data
DecryptResult decryptResult = await cryptoClient.DecryptAsync(EncryptionAlgorithm.RsaOaep
string decryptedData = Encoding.UTF8.GetString(decryptResult.Plaintext);
Certificate Management:
var certificateClient = new CertificateClient(new Uri(keyVaultUrl), credential);
// Create self-signed certificate
var certificatePolicy = new CertificatePolicy("Self", "CN=mydomain.com")
{
KeyType = CertificateKeyType.Rsa,
KeySize = 2048,
ReuseKey = false,
ValidityInMonths = 12
};
CertificateOperation operation = await certificateClient.StartCreateCertificateAsync("MyC
KeyVaultCertificateWithPolicy certificate = await operation.WaitForCompletionAsync();
// Get certificate
KeyVaultCertificateWithPolicy retrievedCertificate = await certificateClient.GetCertifica
// Import certificate
byte[] certificateBytes = File.ReadAllBytes("certificate.pfx");
ImportCertificateOptions importOptions = new ImportCertificateOptions("ImportedCertificat
{
Password = "certificatePassword"
};
KeyVaultCertificateWithPolicy importedCertificate = await certificateClient.ImportCertifi
Key Vault References in App Service
Configuration Reference:
// appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "@Microsoft.KeyVault(VaultName=myvault;SecretName=DatabaseConnec
}
}
// Alternative URI format
{
"ConnectionStrings": {
"DefaultConnection": "@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/s
}
}
Application Usage:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Connection string is automatically resolved from Key Vault
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")))
}
}
4. Managed Identities
Core Concepts
Managed Identities provide Azure services with automatically managed identities in Azure AD:
System-Assigned Identity:
Lifecycle tied to the resource
Automatically created and deleted with the resource
1:1 relationship with Azure resource
User-Assigned Identity:
Standalone Azure resource
Can be assigned to multiple resources
Independent lifecycle management
Configuration and Usage
Enable System-Assigned Identity:
# Enable for App Service
az webapp identity assign --name myapp --resource-group mygroup
# Enable for Virtual Machine
az vm identity assign --name myvm --resource-group mygroup
# Enable for Function App
az functionapp identity assign --name myfunctionapp --resource-group mygroup
Create and Assign User-Assigned Identity:
# Create user-assigned identity
az identity create --name myuserassignedidentity --resource-group mygroup
# Assign to App Service
az webapp identity assign --name myapp --resource-group mygroup --identities /subscriptio
Access Azure Resources with Managed Identity:
// Using DefaultAzureCredential (automatically detects managed identity)
var credential = new DefaultAzureCredential();
// Access Key Vault
var secretClient = new SecretClient(new Uri("https://myvault.vault.azure.net/"), credenti
var secret = await secretClient.GetSecretAsync("MySecret");
// Access Storage Account
var blobServiceClient = new BlobServiceClient(new Uri("https://mystorageaccount.blob.core
// Access Cosmos DB
var cosmosClient = new CosmosClient("https://mycosmosaccount.documents.azure.net/", crede
// Access Service Bus
var serviceBusClient = new ServiceBusClient("myservicebusnamespace.servicebus.windows.net
Explicit Managed Identity Usage:
// For user-assigned identity
var credential = new ManagedIdentityCredential(clientId: "user-assigned-identity-client-i
// For system-assigned identity (default)
var credential = new ManagedIdentityCredential();
// Alternative: Explicitly specify system-assigned
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ManagedIdentityClientId = null // Use system-assigned
});
5. Role-Based Access Control (RBAC)
Core Concepts
RBAC provides fine-grained access management for Azure resources:
Security Principal: Who (User, Group, Service Principal, Managed Identity)
Role Definition: What permissions (built-in or custom roles)
Scope: Where (Subscription, Resource Group, Resource)
Built-in Roles
Role Description Use Case
Owner Full access including access management Resource administrators
Contributor Full access except access management Developers, operators
Reader View all resources but no changes Auditors, monitoring
User Access Administrator Manage user access to resources Access management
Service-Specific Roles:
Service Role Permissions
Storage Storage Blob Data Owner Full access to blob containers and data
Storage Storage Blob Data Contributor Read, write, delete blob containers and data
Storage Storage Blob Data Reader Read blob containers and data
Key Vault Key Vault Administrator Full access to all Key Vault operations
Key Vault Key Vault Secrets User Read secret contents
Cosmos DB Cosmos DB Built-in Data Contributor Read, write, delete items in Cosmos DB
Custom Roles
{
"Name": "Custom Storage Blob Reader",
"Id": null,
"IsCustom": true,
"Description": "Custom role to read storage blobs with additional permissions",
"Actions": [
"Microsoft.Storage/storageAccounts/blobServices/containers/read",
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read"
],
"NotActions": [],
"DataActions": [
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read"
],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/{subscription-id}"
]
}
Create Custom Role:
az role definition create --role-definition custom-role.json
Role Assignments
# Assign built-in role to user
az role assignment create \
--assignee user@domain.com \
--role "Storage Blob Data Contributor" \
--scope /subscriptions/{subscription}/resourceGroups/{resourcegroup}/providers/Microsof
# Assign role to managed identity
az role assignment create \
--assignee {managed-identity-principal-id} \
--role "Key Vault Secrets User" \
--scope /subscriptions/{subscription}/resourceGroups/{resourcegroup}/providers/Microsof
# Assign role to service principal
az role assignment create \
--assignee {service-principal-id} \
--role "Cosmos DB Built-in Data Contributor" \
--scope /subscriptions/{subscription}/resourceGroups/{resourcegroup}/providers/Microsof
PowerShell Role Management:
# Assign role
New-AzRoleAssignment -SignInName "user@domain.com" -RoleDefinitionName "Contributor" -Sco
# Remove role assignment
Remove-AzRoleAssignment -SignInName "user@domain.com" -RoleDefinitionName "Contributor" -
# Get role assignments
Get-AzRoleAssignment -Scope "/subscriptions/{subscription}/resourceGroups/{resourcegroup}
6. Secure Configuration and Networking
Network Security
Virtual Network Integration:
# Create VNet integration for App Service
az webapp vnet-integration add --name myapp --resource-group mygroup --vnet myvnet --subn
Private Endpoints:
# Create private endpoint for Storage Account
az network private-endpoint create \
--name mystoragepe \
--resource-group mygroup \
--vnet-name myvnet \
--subnet mysubnet \
--private-connection-resource-id /subscriptions/{subscription}/resourceGroups/{resource
--connection-name mystorageconnection \
--group-id blob
Access Restrictions:
// Configure IP restrictions in ARM template
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2020-06-01",
"name": "[concat(parameters('siteName'), '/web')]",
"properties": {
"ipSecurityRestrictions": [
{
"ipAddress": "192.168.1.0/24",
"action": "Allow",
"priority": 100,
"name": "AllowOfficeNetwork"
},
{
"ipAddress": "0.0.0.0/0",
"action": "Deny",
"priority": 200,
"name": "DenyAll"
}
]
}
}
SSL/TLS Configuration
App Service Managed Certificate:
# Create managed certificate
az webapp config ssl bind --name myapp --resource-group mygroup --certificate-thumbprint
Custom Certificate from Key Vault:
# Import certificate from Key Vault
az webapp config ssl import --name myapp --resource-group mygroup --key-vault myvault --k
Configuration Security
Secure Application Settings:
// Use Key Vault references
@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/DatabasePassword/)
// Use managed identity for authentication
var credential = new DefaultAzureCredential();
var configurationBuilder = new ConfigurationBuilder()
.AddAzureKeyVault(vaultUri, credential);
Connection String Encryption:
// App Service automatically encrypts connection strings
// Access through configuration
public class Startup
{
private readonly IConfiguration _configuration;
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
// Connection string is automatically decrypted
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(_configuration.GetConnectionString("DefaultConnection"))
}
}
Security Best Practices
Authentication and Authorization
1. Use Managed Identities: Eliminate stored credentials
2. Implement Least Privilege: Grant minimal required permissions
3. Use RBAC over Access Policies: Consistent security model
4. Enable MFA: Multi-factor authentication for users
5. Implement Conditional Access: Risk-based access policies
Secret Management
1. Use Key Vault: Centralized secret management
2. Implement Secret Rotation: Regular credential updates
3. Use Key Vault References: Avoid storing secrets in configuration
4. Monitor Access: Enable logging and alerting
5. Separate Environments: Different Key Vaults per environment
Network Security
1. Private Endpoints: Secure connectivity to Azure services
2. VNet Integration: Isolate application traffic
3. Network Security Groups: Control inbound/outbound traffic
4. Application Gateway: Web application firewall capabilities
5. DDoS Protection: Protect against volumetric attacks
Practice Scenarios
Scenario 1: Secure Multi-Tier Application
Requirements: Web app accessing database and storage with secure authentication.
Solution:
1. Enable managed identity for App Service
2. Store connection strings in Key Vault
3. Use Key Vault references in application settings
4. Implement RBAC for resource access
5. Configure private endpoints for backend services
Scenario 2: Service-to-Service Authentication
Requirements: Function App processing messages from Service Bus and storing results in
Cosmos DB.
Solution:
1. Create user-assigned managed identity
2. Assign appropriate RBAC roles for Service Bus and Cosmos DB
3. Use DefaultAzureCredential in Function App
4. Implement secure configuration using Key Vault
5. Monitor access with Azure Monitor
Scenario 3: External API Integration
Requirements: Securely access third-party APIs from Azure Functions.
Solution:
1. Store API keys in Key Vault
2. Use managed identity to access Key Vault
3. Implement certificate-based authentication where possible
4. Use HTTP client factory with secure defaults
5. Implement retry policies and circuit breakers
Exam Tips
1. Understand managed identity types: System vs user-assigned differences
2. Know RBAC scope hierarchy: Subscription > Resource Group > Resource
3. Master Key Vault operations: Secrets, keys, certificates, access policies
4. Memorize Graph API permissions: Delegated vs application permissions
5. Practice MSAL authentication flows: Authorization code, client credentials
6. Security best practices: Always choose most secure option
7. Monitor and audit: Understand logging and alerting capabilities
This completes Module 3 on Azure Security Implementation, providing comprehensive coverage
of identity, access management, and security best practices essential for the AZ-204
certification.