EngineeringSolution ArchitectSecurity and Observability

Session 03 - Zero Trust Architecture

Zero Trust Principles

Zero Trust là security model dựa trên nguyên tắc "Never trust, always verify" - không tin tưởng bất kỳ request nào dù từ bên trong hay bên ngoài network.

Ba trụ cột

So sánh Traditional vs Zero Trust

AspectTraditional (Perimeter)Zero Trust
Trust modelTrust inside networkTrust nothing
AuthenticationTại network boundaryMọi request
Network designFlat internal networkMicro-segmented
Access controlVPN = full accessLeast privilege per resource
MonitoringPerimeter-focusedEnd-to-end

Azure AD / Entra ID Integration

Authentication Flow cho .NET API

csharp
// Program.cs - Azure AD authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

// appsettings.json
// {
//   "AzureAd": {
//     "Instance": "https://login.microsoftonline.com/",
//     "TenantId": "your-tenant-id",
//     "ClientId": "your-api-client-id",
//     "Audience": "api://your-api-client-id"
//   }
// }

// Scope-based authorization
builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ReadOrders", policy =>
        policy.RequireScope("Orders.Read"))
    .AddPolicy("WriteOrders", policy =>
        policy.RequireScope("Orders.ReadWrite"));

// Controller usage
[Authorize]
[RequiredScope("Orders.Read")]
[HttpGet("orders")]
public async Task<IActionResult> GetOrders() { /* ... */ }

Token Validation Checklist

csharp
// Explicit token validation parameters
services.Configure<JwtBearerOptions>(
    JwtBearerDefaults.AuthenticationScheme, options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,        // Verify token issuer
        ValidateAudience = true,      // Verify intended audience
        ValidateLifetime = true,      // Check expiration
        ValidateIssuerSigningKey = true, // Verify signature
        RequireExpirationTime = true, // Token must have exp claim
        RequireSignedTokens = true,   // Must be signed
        ClockSkew = TimeSpan.FromMinutes(1) // Reduce from default 5 min
    };
});

Managed Identity Playbook

Managed Identity loại bỏ hoàn toàn secrets cho Azure resource communication.

System-assigned vs User-assigned

FeatureSystem-assignedUser-assigned
LifecycleTied to resourceIndependent
Sharing1:1 với resourceNhiều resources share
Use caseSingle serviceShared across services
ManagementSimplerMore flexible

Setup - Azure CLI

bash
# Enable system-assigned managed identity cho App Service
az webapp identity assign \
    --name my-web-api \
    --resource-group my-rg

# Grant access tới SQL Database
az sql server ad-admin create \
    --server my-sql-server \
    --resource-group my-rg \
    --display-name "ManagedIdentityAdmin" \
    --object-id <managed-identity-object-id>

# Grant access tới Key Vault
az keyvault set-policy \
    --name my-key-vault \
    --object-id <managed-identity-object-id> \
    --secret-permissions get list

# Grant access tới Storage
az role assignment create \
    --role "Storage Blob Data Reader" \
    --assignee <managed-identity-object-id> \
    --scope /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Storage/storageAccounts/{account}

.NET Code - DefaultAzureCredential

csharp
using Azure.Identity;

// DefaultAzureCredential tự động chọn credential phù hợp:
// Local dev: Visual Studio / Azure CLI / Environment Variables
// Azure: Managed Identity
var credential = new DefaultAzureCredential();

// SQL Database
builder.Services.AddDbContext<AppDbContext>(opts =>
{
    var conn = new SqlConnection(builder.Configuration.GetConnectionString("Sql"));
    conn.AccessToken = new DefaultAzureCredential()
        .GetToken(new TokenRequestContext(
            new[] { "https://database.windows.net/.default" }))
        .Token;
    opts.UseSqlServer(conn);
});

// Key Vault
builder.Configuration.AddAzureKeyVault(
    new Uri("https://my-key-vault.vault.azure.net/"),
    credential);

// Blob Storage
builder.Services.AddSingleton(new BlobServiceClient(
    new Uri("https://mystorageaccount.blob.core.windows.net"),
    credential));

// Service Bus
builder.Services.AddSingleton(new ServiceBusClient(
    "my-namespace.servicebus.windows.net",
    credential));

Conditional Access Policies

Common Policies

PolicyConditionControl
MFA for adminsRole = Global Admin, App AdminRequire MFA
Block legacy authClient app = Other clientsBlock access
Compliant devicesDevice compliance = Not compliantBlock access
Location-basedLocation = Outside allowed countriesBlock or require MFA
Risk-basedSign-in risk = HighRequire MFA + password change
Session controlsApp = sensitive appsLimited session lifetime (1h)

Implementation trong Azure

bash
# Conditional Access via Microsoft Graph API
az rest --method POST \
    --uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" \
    --body '{
        "displayName": "Require MFA for Admin Roles",
        "state": "enabled",
        "conditions": {
            "users": {
                "includeRoles": [
                    "62e90394-69f5-4237-9190-012177145e10"
                ]
            },
            "applications": {
                "includeApplications": ["All"]
            }
        },
        "grantControls": {
            "operator": "OR",
            "builtInControls": ["mfa"]
        }
    }'

Network Micro-segmentation

Azure Network Architecture

NSG Rules Example

bash
# Data subnet: chỉ cho phép traffic từ App subnet
az network nsg rule create \
    --nsg-name data-subnet-nsg \
    --name AllowAppSubnet \
    --priority 100 \
    --source-address-prefixes 10.0.1.0/24 \
    --destination-port-ranges 1433 6380 443 \
    --access Allow \
    --direction Inbound

# Block tất cả traffic khác
az network nsg rule create \
    --nsg-name data-subnet-nsg \
    --name DenyAll \
    --priority 4096 \
    --source-address-prefixes '*' \
    --access Deny \
    --direction Inbound

mTLS Between Services

csharp
// Service-to-service mTLS setup
builder.Services.AddHttpClient("PaymentService", client =>
{
    client.BaseAddress = new Uri("https://payment-service.internal");
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
    var handler = new HttpClientHandler();

    // Load client certificate
    var cert = new X509Certificate2("client-cert.pfx", "password");
    handler.ClientCertificates.Add(cert);

    // Validate server certificate
    handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
    {
        // Verify against known CA
        return errors == SslPolicyErrors.None;
    };

    return handler;
});

Azure Key Vault for Secrets

Best Practices

PracticeMô tả
No secrets in codeZero secrets trong appsettings, environment variables
Managed Identity accessKhông dùng client secret để access Key Vault
Secret rotationAutomated rotation cho database passwords, API keys
Soft delete + Purge protectionBật cả hai cho production vaults
Access policiesPrinciple of least privilege - chỉ get + list cho app
Audit loggingEnable diagnostic settings → Log Analytics

Trade-offs

Quyết địnhProCon
Full Zero TrustMaximum securityPhức tạp, latency tăng (thêm auth hops)
Private Endpoints everywhereNo public exposureChi phí tăng, debugging khó hơn
Managed Identity onlyNo secrets to manageChỉ hoạt động trong Azure
Strict Conditional AccessGiảm unauthorized accessUser friction, support tickets tăng
mTLS between servicesStrong service identityCertificate management overhead