---
title: "Project: Building a Zero Trust Identity Architecture in Azure"
description: "Moving beyond basic user management to implement a production-grade Zero Trust architecture. This hands-on project demonstrates custom RBAC roles, management group hierarchies, and least-privilege security design patterns for a fictional FinTech client."
canonical: "https://zainahmed.net/blog/zero-trust-identity-azure"
published: "2026-01-02"
---

# Project: Building a Zero Trust Identity Architecture in Azure

> Author: Zain Ahmed | Cloud & DevOps Engineer
> Published: 2026-01-02
> Read Time: 20 min read
> Category: Cloud Security
> Tags: Azure, Zero Trust, Security, Entra ID, RBAC, Identity, AZ-104, DevSecOps
> Canonical URL: https://zainahmed.net/blog/zero-trust-identity-azure

## Excerpt
Moving beyond basic user management to implement a production-grade Zero Trust architecture. This hands-on project demonstrates custom RBAC roles, management group hierarchies, and least-privilege security design patterns for a fictional FinTech client.

---

Creating a user is one small part of identity management. This project focuses on the permissions and controls needed to keep access secure as an organization grows.

In this project, I simulated a real-world scenario for a fictional FinTech client, **FinCore Systems**. The goal was to replace manually assigned permissions and implement a **Zero Trust architecture** using Microsoft Entra ID and Custom RBAC (Role-Based Access Control).

If you are studying for the **AZ-104** or just want to learn how to secure Azure like a pro, follow this step-by-step guide.

<div class="my-8 p-5 border rounded-none bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 dark:border-gray-700 shadow-none">
  <div class="flex items-center gap-2 mb-3">
    <span class="px-2 py-1 text-xs font-bold text-blue-600 bg-blue-100 rounded-none dark:bg-blue-900/30 dark:text-blue-400">AZ-104 Labs</span>
    <span class="text-sm font-semibold text-gray-600 dark:text-gray-300">Curriculum Mapping</span>
  </div>
  <p class="text-sm text-gray-600 dark:text-gray-300 mb-3 leading-relaxed">
    This project combines and extends the concepts from the official Microsoft Learning labs. It transforms the isolated tasks into a cohesive, production-ready solution.
  </p>
  <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
    <div class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-200">
      <div class="h-2 w-2 rounded-none bg-blue-500"></div>
      <strong>Lab 01:</strong> Manage Entra ID Identities
    </div>
    <div class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-200">
      <div class="h-2 w-2 rounded-none bg-purple-500"></div>
      <strong>Lab 02a:</strong> Subscriptions & RBAC
    </div>
  </div>
</div>

---

## 🏢 The Business Scenario

**Client:** FinCore Systems (FinTech)

**The Problem:** The "Help Desk" team has too much power. They currently have **Contributor** access, which allows them to delete production databases.

**The Requirement:** We need a custom security role that allows them to:
- ✅ **Restart Virtual Machines** (to fix issues).
- ✅ **Open Support Tickets** (to get help).
- ❌ **Strictly Block** them from creating new resources or registering expensive service providers (Shadow IT).

---

## 🏗️ The Architecture

Instead of assigning permissions to individuals (which is unscalable), we will build a hierarchy:

1. **Identity:** Users are assigned to an Entra ID Group (`grp-fincore-support`).
2. **Scope:** We create a Management Group (`mg-fincore-corp`) to govern all subscriptions.
3. **Permissions:** We attach a Custom RBAC Role to the Management Group, which trickles down to everything below it.

<div class="my-6 p-4 border-l-4 border-blue-500 bg-blue-500/10 rounded-none">
  <div class="flex items-center gap-2 font-bold text-blue-600 mb-2">
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shield-check"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10"/><path d="m9 12 2 2 4-4"/></svg>
    Zero Trust Principle
  </div>
  <p class="text-sm text-blue-700/90 dark:text-blue-400/90 !mt-0">
    Never trust, always verify. Permissions are explicitly granted, never assumed. Every action requires validation.
  </p>
</div>

---

## 🚀 Step-by-Step Implementation

### Phase 1: Identity Management (Entra ID)

First, we need to create the "Who." We **never** assign roles to users directly; we assign them to groups.

#### 1. Create the Security Group

I started by creating a dedicated security group for the support team. This ensures that if we hire 50 new engineers, we just add them to this group, and they inherit the permissions automatically.

- **Group Name:** `grp-fincore-support`
- **Type:** Security

![Starting group creation](/assets/images/articles/zero-trust-identity-azure/01-create-group-start.webp)
![Configuring group details](/assets/images/articles/zero-trust-identity-azure/02-create-group-details.webp)
![Adding members to group](/assets/images/articles/zero-trust-identity-azure/03-add-members-to-group.webp)
![Group creation confirmation](/assets/images/articles/zero-trust-identity-azure/04-group-created-confirmation.webp)

<div class="my-6 p-4 border-l-4 border-green-500 bg-green-500/10 rounded-none">
  <div class="flex items-center gap-2 font-bold text-green-600 mb-2">
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-lightbulb"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg>
    Best Practice
  </div>
  <p class="text-sm text-green-700/90 dark:text-green-400/90 !mt-0">
    <strong>Always assign RBAC roles to groups, not individual users.</strong> This provides scalability and reduces administrative overhead when employees change roles or leave the organization.
  </p>
</div>

#### 2. Create the Test User

Next, I created a user named **Alex Support** to act as our "victim" for testing. Crucially, I set the **Usage Location** to the United States (a common oversight that blocks license assignments later).

![Creating test user](/assets/images/articles/zero-trust-identity-azure/05-create-user-alex.webp)

---

### Phase 2: Governance Scope (Management Groups)

To manage policies at scale, we don't want to touch every individual subscription. I created a **Management Group** to act as a "Root Folder" for the organization.

- **ID:** `mg-fincore-corp`
- **Display Name:** FinCore Corporate Root

![Management Group Hierarchy](/assets/images/articles/zero-trust-identity-azure/06-management-group-hierarchy.webp)

<div class="my-8 rounded-none border bg-card text-card-foreground shadow-none overflow-hidden">
  <div class="bg-muted/50 p-4 border-b flex items-center gap-2">
     <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-info"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
     <span class="font-semibold">Why Management Groups?</span>
  </div>
  <div class="p-6 space-y-4">
    <p class="text-sm text-muted-foreground m-0 leading-relaxed">
      Management Groups allow you to apply governance at scale. Instead of assigning a role to 50 individual subscriptions, you assign it <strong>once</strong> at the Management Group level, and it automatically cascades down to all child subscriptions and resources.
    </p>
  </div>
</div>

---

### Phase 3: The "Least Privilege" Custom Role

This is the core of the project. The built-in **"Support Request Contributor"** role was too weak (can't restart VMs), but **"Virtual Machine Contributor"** was too dangerous (can delete VMs).

I created a **Custom Role** by cloning the Support role and modifying it.

#### 1. Adding Permissions (The "Allow" List)

We need to create a role that specifically allows VM restart but denies everything else initially.

![Starting IAM Role Creation](/assets/images/articles/zero-trust-identity-azure/07-iam-add-role-start.webp)
![Defining permissions](/assets/images/articles/zero-trust-identity-azure/08-create-custom-role-permissions.webp)

I explicitly added `Microsoft.Compute/virtualMachines/restart/action`. This gives Alex the power to reboot a frozen server without giving him the power to delete it.

![Adding VM Restart permission](/assets/images/articles/zero-trust-identity-azure/09-add-vm-restart-permission.webp)



#### 2. Blocking Shadow IT (The "NotAction" List)

To prevent the Help Desk from accidentally enabling expensive services (like AI or Blockchain), I added `Microsoft.Support/register/action` to the **NotActions** list. This effectively "denies" the ability to register new resource providers.

![Adding NotActions](/assets/images/articles/zero-trust-identity-azure/10-add-not-action-register.webp)
![Reviewing custom role](/assets/images/articles/zero-trust-identity-azure/11-custom-role-review.webp)

<div class="my-6 p-4 border-l-4 border-yellow-500 bg-yellow-500/10 rounded-none">
  <div class="flex items-center gap-2 font-bold text-yellow-600 mb-2">
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-alert-triangle"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
    Common Misconception
  </div>
  <p class="text-sm text-yellow-700/90 dark:text-yellow-500/90 !mt-0">
    <strong>NotActions</strong> is NOT a "Deny" statement. It simply <em>subtracts</em> permissions from the Actions list in that specific role. If a user has another role that grants the permission, they will still have access.
  </p>
</div>

#### 3. The Final Configuration Code

This JSON represents the final "Infrastructure as Code" artifact for the role.

<div class="bg-slate-950 rounded-none border border-slate-800 shadow-none my-8 overflow-hidden group">
  <div class="flex items-center justify-between px-4 py-3 bg-slate-900 border-b border-slate-800">
    <div class="flex items-center gap-3">
      <div class="flex gap-1.5 group-hover:opacity-100 opacity-60 transition-opacity">
        <div class="w-3 h-3 rounded-none bg-[#FF5F56] border border-[#E0443E]/50"></div>
        <div class="w-3 h-3 rounded-none bg-[#FFBD2E] border border-[#DEA123]/50"></div>
        <div class="w-3 h-3 rounded-none bg-[#27C93F] border border-[#1AAB29]/50"></div>
      </div>
      <div class="h-4 w-[1px] bg-slate-700 mx-1"></div>
      <div class="flex items-center gap-2 text-xs font-mono text-blue-400 font-bold">
        <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><path d="M12 18v-6"></path><path d="M8 15h8"></path></svg>
        RoleDefinition.json
      </div>
    </div>
    <div class="flex items-center gap-2">
        <span class="text-[10px] text-slate-500 font-sans tracking-wider font-bold">ARM</span>
    </div>
  </div>
  <div class="p-0 bg-slate-950">
<pre class="!my-0 !rounded-none !bg-transparent !border-0 text-sm leading-relaxed custom-scrollbar !p-6 font-mono"><code class="language-json !bg-transparent !p-0 !text-sm"><span class="text-yellow-500">{</span>
  <span class="text-sky-400">"properties"</span><span class="text-slate-400">:</span> <span class="text-yellow-500">{</span>
    <span class="text-sky-400">"roleName"</span><span class="text-slate-400">:</span> <span class="text-orange-300">"FinCore Support Specialist"</span><span class="text-slate-400">,</span>
    <span class="text-sky-400">"description"</span><span class="text-slate-400">:</span> <span class="text-orange-300">"Can open tickets and restart VMs. Cannot register new providers."</span><span class="text-slate-400">,</span>
    <span class="text-sky-400">"assignableScopes"</span><span class="text-slate-400">:</span> <span class="text-purple-400">[</span>
      <span class="text-orange-300">"/providers/Microsoft.Management/managementGroups/mg-fincore-corp"</span>
    <span class="text-purple-400">]</span><span class="text-slate-400">,</span>
    <span class="text-sky-400">"permissions"</span><span class="text-slate-400">:</span> <span class="text-purple-400">[</span>
      <span class="text-yellow-500">{</span>
        <span class="text-sky-400">"actions"</span><span class="text-slate-400">:</span> <span class="text-blue-400">[</span>
          <span class="text-orange-300">"Microsoft.Authorization/*/read"</span><span class="text-slate-400">,</span>
          <span class="text-orange-300">"Microsoft.Resources/subscriptions/resourceGroups/read"</span><span class="text-slate-400">,</span>
          <span class="text-orange-300">"Microsoft.Support/*"</span><span class="text-slate-400">,</span>
          <span class="text-orange-300">"Microsoft.Compute/virtualMachines/restart/action"</span>
        <span class="text-blue-400">]</span><span class="text-slate-400">,</span>
        <span class="text-sky-400">"notActions"</span><span class="text-slate-400">:</span> <span class="text-blue-400">[</span>
          <span class="text-orange-300">"Microsoft.Support/register/action"</span>
        <span class="text-blue-400">]</span><span class="text-slate-400">,</span>
        <span class="text-sky-400">"dataActions"</span><span class="text-slate-400">:</span> <span class="text-blue-400">[]</span><span class="text-slate-400">,</span>
        <span class="text-sky-400">"notDataActions"</span><span class="text-slate-400">:</span> <span class="text-blue-400">[]</span>
      <span class="text-yellow-500">}</span>
    <span class="text-purple-400">]</span>
  <span class="text-yellow-500">}</span>
<span class="text-yellow-500">}</span></code></pre>
  </div>
</div>

There are three critical components to this configuration:

1.  **AssignableScopes**: The role is scoped to `/mg-fincore-corp`. This means it *cannot* be assigned at the Root Management Group (too broad) or a single Subscription (too narrow). It exists exactly where FinCore operates.
2.  **Actions**: We explicitly grant `Microsoft.Support/*` for ticketing and the *specific* `restart/action` for VMs. This avoids the dangerous `write` or `delete` permissions found in standard Contributor roles.
3.  **NotActions**: This acts as a safety filter. Even if another policy or role tries to grant "Support" access, this role explicitly carves out the ability to `register` new resource providers, preventing accidental cost spikes from "Shadow IT" service headers.

---

### Phase 4: Assigning the Role

With the role created, we now assign it to our security group at the Management Group scope. This ensures that the permissions trickle down to all subscriptions and resources within our organization.

![Starting role assignment](/assets/images/articles/zero-trust-identity-azure/12-role-assignment-start.webp)
![Selecting the custom role](/assets/images/articles/zero-trust-identity-azure/13-role-assignment-select-role.webp)
![Selecting the target group](/assets/images/articles/zero-trust-identity-azure/14-role-assignment-select-group.webp)

---

### Phase 5: The "Hacker" Verification

A security architecture is only good if it works. I logged in as **Alex** (using an Incognito window) to test the boundaries.

#### Test 1: VM Operations (The "Least Privilege" Test)

First, I attempted to **Restart** a Virtual Machine. Since this action was explicitly allowed in our custom role, it should work.

![VM Restart Success](/assets/images/articles/zero-trust-identity-azure/15-test-vm-restart-success.webp)

**Success!** The command executed without issues.

Next, I attempted to **Delete** the same VM. Since this action was NOT in our custom role (and `Delete` is a destructive action), it should be blocked.

![VM Delete Denied](/assets/images/articles/zero-trust-identity-azure/16-test-vm-delete-denied.webp)

**Blocked!** Azure's ARM layer correctly prevented the action.

#### Test 2: Support Operations

I attempted to open a **Support Ticket**. The custom role successfully allowed access to the support blade.

![Opening Support Request](/assets/images/articles/zero-trust-identity-azure/17-test-support-ticket-start.webp)
![Support Ticket Success](/assets/images/articles/zero-trust-identity-azure/18-test-support-ticket-success.webp)

<div class="my-6 p-4 border-l-4 border-green-500 bg-green-500/10 rounded-none">
  <div class="flex items-center gap-2 font-bold text-green-600 mb-2">
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-circle-2"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>
    Test Passed
  </div>
  <p class="text-sm text-green-700/90 dark:text-green-400/90 !mt-0">
    Alex can successfully perform legitimate support operations. The role grants exactly what is neededno more, no less.
  </p>
</div>

#### Test 3: Governance Scope (Blocked)

I attempted to create a new **Resource Group**. As expected, the Zero Trust policy kicked in.

<div class="my-6 p-4 border-l-4 border-red-500 bg-red-500/10 rounded-none">
  <div class="flex items-center gap-2 font-bold text-red-600 mb-2">
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-shield-x"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10"/><path d="m14.5 9-5 5"/><path d="m9.5 9 5 5"/></svg>
    Access Denied (Expected)
  </div>
  <p class="text-sm text-red-700/90 dark:text-red-400/90 !mt-0">
    <strong>Authorization Failed:</strong> The user 'alex.support@fincore.com' does not have authorization to perform action 'Microsoft.Resources/resourceGroups/write' over scope '/subscriptions/xxxx'.
  </p>
</div>

**Perfect!** The guardrails are working exactly as designed.

---

## 📊 Key Takeaways

<div className="grid gap-6 md:grid-cols-2 my-8 not-prose">
  
  <div className="rounded-none border border-teal-500/20 bg-teal-500/5 text-card-foreground shadow-none flex flex-col relative overflow-hidden ring-1 ring-teal-500/10">
    <div className="absolute top-0 right-0 p-2 opacity-[0.03]">
        <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="currentColor"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
    </div>
    <div className="p-4 border-b border-teal-500/10 bg-teal-500/10">
        <h3 className="font-bold text-base flex items-center gap-2 m-0 text-teal-600 dark:text-teal-400">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-users"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
            Identity Design
        </h3>
    </div>
    <div className="p-4 flex flex-col flex-1 gap-4">
        <p className="text-sm text-muted-foreground m-0 leading-relaxed">Use <strong>Security Groups</strong> for role assignments, not individual users. This ensures scalability and reduces administrative burden.</p>
        <div className="mt-auto rounded-none bg-teal-100 dark:bg-teal-900/30 p-3 text-xs font-medium text-teal-800 dark:text-teal-200 border border-teal-200 dark:border-teal-800/50">
            <strong>Best Practice:</strong><br/>Always assign RBAC roles to groups. When employees change roles or leave, simply update group membership instead of hunting down individual assignments.
        </div>
    </div>
  </div>

  <div className="rounded-none border border-blue-500/20 bg-blue-500/5 text-card-foreground shadow-none flex flex-col relative overflow-hidden ring-1 ring-blue-500/10">
    <div className="absolute top-0 right-0 p-2 opacity-[0.03]">
        <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="currentColor"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
    </div>
    <div className="p-4 border-b border-blue-500/10 bg-blue-500/10">
        <h3 className="font-bold text-base flex items-center gap-2 m-0 text-blue-600 dark:text-blue-400">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-lock"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
            Least Privilege
        </h3>
    </div>
    <div className="p-4 flex flex-col flex-1 gap-4">
        <p className="text-sm text-muted-foreground m-0 leading-relaxed">Built-in roles are often too broad. Use <strong>Custom RBAC Roles</strong> to grant exactly the permissions needednothing more.</p>
        <div className="mt-auto rounded-none bg-blue-100 dark:bg-blue-900/30 p-3 text-xs font-medium text-blue-800 dark:text-blue-200 border border-blue-200 dark:border-blue-800/50">
            <strong>Example:</strong><br/>The "Contributor" role allows VM deletion. Create a custom "VM Operator" role that only allows start/stop/restart actions.
        </div>
    </div>
  </div>

  <div className="rounded-none border border-purple-500/20 bg-purple-500/5 text-card-foreground shadow-none flex flex-col relative overflow-hidden ring-1 ring-purple-500/10">
      <div className="absolute top-0 right-0 p-2 opacity-[0.03]">
        <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>
    </div>
    <div className="p-4 border-b border-purple-500/10 bg-purple-500/10">
        <h3 className="font-bold text-base flex items-center gap-2 m-0 text-purple-600 dark:text-purple-400">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-layers"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>
            Hierarchy Design
        </h3>
    </div>
    <div className="p-4 flex flex-col flex-1 gap-4">
        <p className="text-sm text-muted-foreground m-0 leading-relaxed">Use <strong>Management Groups</strong> to apply governance at scale. Permissions cascade down automatically to all child resources.</p>
        <div className="mt-auto rounded-none bg-purple-100 dark:bg-purple-900/30 p-3 text-xs font-medium text-purple-800 dark:text-purple-200 border border-purple-200 dark:border-purple-800/50">
            <strong>Efficiency:</strong><br/>Assign a role once at the Management Group level instead of 50 times across individual subscriptions.
        </div>
    </div>
  </div>

  <div className="rounded-none border border-green-500/20 bg-green-500/5 text-card-foreground shadow-none flex flex-col relative overflow-hidden ring-1 ring-green-500/10">
      <div className="absolute top-0 right-0 p-2 opacity-[0.03]">
        <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="currentColor"><path d="M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5s-2.5-1.1-2.5-2.5V2"/><path d="M8.5 2h7"/><path d="M14.5 16h-5"/></svg>
    </div>
    <div className="p-4 border-b border-green-500/10 bg-green-500/10">
        <h3 className="font-bold text-base flex items-center gap-2 m-0 text-green-600 dark:text-green-400">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-test-tube"><path d="M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5s-2.5-1.1-2.5-2.5V2"/><path d="M8.5 2h7"/><path d="M14.5 16h-5"/></svg>
            Testing
        </h3>
    </div>
    <div className="p-4 flex flex-col flex-1 gap-4">
        <p className="text-sm text-muted-foreground m-0 leading-relaxed">Always <strong>test your roles</strong> using a non-privileged account. Verify both positive cases (can do job) and negative cases (cannot break things).</p>
        <div className="mt-auto rounded-none bg-green-100 dark:bg-green-900/30 p-3 text-xs font-medium text-green-800 dark:text-green-200 border border-green-200 dark:border-green-800/50">
            <strong>Testing Method:</strong><br/>Use an Incognito window to log in as the test user. Attempt both allowed actions and restricted actions to verify the role works as designed.
        </div>
    </div>
  </div>
</div>

---

## 🎯 Conclusion

Building a **Zero Trust Identity Architecture** is not about making access harderit's about making access **smarter**. By combining:

- **Entra ID Security Groups** (for identity)
- **Management Groups** (for scope)
- **Custom RBAC Roles** (for least-privilege permissions)

...we created a system that is both **secure** and **scalable**. The Help Desk team can do their job effectively, but they cannot accidentally (or maliciously) destroy production resources.

<div class="my-8 rounded-none border bg-card text-card-foreground shadow-none overflow-hidden">
  <div class="bg-gradient-to-r from-teal-500/10 to-blue-500/10 p-6 border-b flex items-start gap-4">
     <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-graduation-cap mt-1 flex-shrink-0"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></svg>
     <div>
       <span class="font-semibold text-lg block mb-2">For AZ-104 Candidates</span>
       <p class="text-sm text-muted-foreground m-0 leading-relaxed">This project covers <strong>multiple exam domains</strong>: Entra ID management, Custom RBAC role creation, Management Group hierarchies, and Zero Trust principles. Understanding these concepts will help you ace identity and governance questions on exam day.</p>
     </div>
  </div>
</div>

If you're preparing for Azure certifications or building production-grade cloud environments, I hope this walkthrough helps you implement security with confidence.

**Next Steps:**
- Implement Conditional Access policies for device compliance
- Add Azure Policy to enforce naming conventions
- Deploy Azure AD Privileged Identity Management (PIM) for just-in-time access

---

*Want to see more cloud architecture projects? Follow my blog for deep dives into Azure, AWS, and DevSecOps best practices.*

---

## Related Endpoints & Navigation
- **All Articles**: [https://zainahmed.net/blog](https://zainahmed.net/blog)
- **Author Profile**: [https://zainahmed.net/about](https://zainahmed.net/about)
- **Machine-Readable LLM Manifest**: [https://zainahmed.net/llms.txt](https://zainahmed.net/llms.txt)
- **RSS Feed**: [https://zainahmed.net/feed.xml](https://zainahmed.net/feed.xml)
