Company: TechCorp Inc
TechCorp is a fast-growing SaaS company with 50+ engineers shipping new features daily. Last month, a junior developer accidentally deleted the production database because they had Owner access everywhere.
The Problem:
Your Challenge: Design and implement environment-based access control
The Solution You'll Build:
DEV Subscription (Junior Playground)├─ Junior devs: Full Contributor access (create, delete, experiment)
├─ Senior devs: Full Contributor access
├─ DevOps: Full Contributor access
└─ Policy: None (safe to break things here)
STAGING Subscription (Validated Changes)
├─ Junior devs: Read-only (can't touch)
├─ Senior devs: Full Contributor access (test changes)
├─ DevOps: Full Contributor access
└─ Policy: Enforce backup tags, encryption
PROD Subscription (Locked Down)
├─ Junior devs: Read-only (observe only)
├─ Senior devs: Read-only (can't modify directly)
├─ DevOps: Full Contributor access (deploy via pipeline)
└─ Policies:
├─ Deny VM deletion
├─ Deny database deletion
├─ Require encryption
├─ Require backup tags
├─ Require premium VM types
└─ Audit all changes
Success Criteria:
Required Knowledge:
Required Permissions:
Cost Note: This lab uses 3 subscriptions. Even if empty, some charges may apply. Use free trial subscriptions if possible.
Total: 120 minutes
Difficulty: Advanced
You need 3 isolated environments with different access rules.
Step 1: Create or Identify Three Subscriptions
You need 3 subscriptions (one for each environment):
Dev Subscription:├─ Name: TechCorp-Dev-Sub or dev-environment
├─ Purpose: Junior developer playground
└─ Existing subscription ID: ____________<em><strong>
Staging Subscription:
├─ Name: TechCorp-Staging-Sub or staging-environment
├─ Purpose: Pre-production testing
└─ Existing subscription ID: </strong></em>_________<em><strong>
Prod Subscription:
├─ Name: TechCorp-Prod-Sub or prod-environment
├─ Purpose: Live customer data
└─ Existing subscription ID: </strong></em>_________<em><strong>
If you don't have 3 subscriptions:
Step 2: Document Subscription IDs
For each subscription:
Dev Subscription ID: </strong></em>__________________________<em><strong>Staging Subscription ID: </strong></em>__________________________<em><strong>
Prod Subscription ID: </strong></em>__________________________<em><strong>
Step 3: Create Entra Groups for Developer Tiers
These groups will determine who gets what access:
Name: grp-junior-developersType: Security
Description: Entry-level developers (limited to Dev environment)
Members: [Add test users representing junior devs]
Name: grp-senior-developersType: Security
Description: Senior developers (all environments, Prod read-only)
Members: [Add test users representing senior devs]
Name: grp-devops-engineersType: Security
Description: DevOps team (full access all environments for deployment)
Members: [Add test users representing DevOps team]
Name: grp-all-developersType: Security
Description: All developers (for nested group management)
Members: grp-junior-developers + grp-senior-developers
Step 4: Document Your Setup
Create a reference table:
SUBSCRIPTION & GROUP MAPPING═════════════════════════════════════════════════════════════
SUBSCRIPTIONS:
├─ Dev: [ID] </strong></em>______________<em><strong>
├─ Staging: [ID] </strong></em>______________<em><strong>
└─ Prod: [ID] </strong></em>______________<em><strong>
ENTRA GROUPS:
├─ grp-junior-developers (Members: </strong></em><strong> people)
├─ grp-senior-developers (Members: </strong><em><strong> people)
├─ grp-devops-engineers (Members: </strong></em>_<em> people)
└─ grp-all-developers (nested group)
READY FOR NEXT STEP: ☐ Yes ☐ No
✅ Complete: All 3 subscriptions accessible
✅ All 4 groups created with correct members
✅ Ready to assign RBAC roles
Assign roles so that each group has the right access for their environment.
Step 1: Configure DEV Subscription Access
Dev is a playground - minimal restrictions.
DEV SUBSCRIPTION: Full access for developmentgrp-junior-developers:
├─ Role: Contributor
├─ Scope: Dev subscription
├─ Effect: Can create, modify, DELETE resources
└─ Reason: Safe to experiment; mistakes are acceptable here
grp-senior-developers:
├─ Role: Contributor
├─ Scope: Dev subscription
├─ Effect: Same as juniors in Dev
└─ Reason: Collaborate with juniors, review their code
grp-devops-engineers:
├─ Role: Contributor
├─ Scope: Dev subscription
├─ Effect: Full access
└─ Reason: Test deployment automation
To implement:
- Role: Contributor
- Scope: Dev Subscription
- Click Assign
Step 2: Configure STAGING Subscription Access
Staging is controlled - only seniors and DevOps can modify.
STAGING SUBSCRIPTION: Controlled changes onlygrp-junior-developers:
├─ Role: Reader
├─ Scope: Staging subscription
├─ Effect: Can VIEW but NOT MODIFY
└─ Reason: Juniors learn by observing, can't break staging
grp-senior-developers:
├─ Role: Contributor
├─ Scope: Staging subscription
├─ Effect: Can create, modify, test before prod
└─ Reason: Validate changes in staging before production
grp-devops-engineers:
├─ Role: Contributor
├─ Scope: Staging subscription
├─ Effect: Full access
└─ Reason: Test deployment pipeline
To implement:
- Role: Reader
- Click Assign
- Role: Contributor
- Click Assign
- Role: Contributor
- Click Assign
Step 3: Configure PROD Subscription Access
Prod is locked down - only DevOps can deploy, everyone else read-only.
PROD SUBSCRIPTION: Locked down - view-only except DevOpsgrp-junior-developers:
├─ Role: Reader
├─ Scope: Prod subscription
├─ Effect: Can VIEW customer data (for debugging)
├─ Cannot: Modify, delete, change anything
└─ Reason: Developers can troubleshoot production issues
grp-senior-developers:
├─ Role: Reader
├─ Scope: Prod subscription
├─ Effect: Can VIEW (same as juniors)
├─ Cannot: Modify directly (must go through DevOps)
└─ Reason: Code review → DevOps deploys → senior verifies
grp-devops-engineers:
├─ Role: Contributor
├─ Scope: Prod subscription
├─ Effect: FULL ACCESS (only them!)
├─ Deploy via pipeline ← Automated, audited
└─ Reason: Controlled deployments with full audit trail
To implement:
- Role: Reader
- Click Assign
- Role: Reader
- Click Assign
- Role: Contributor
- Click Assign
Step 4: Create a RBAC Matrix (Documentation)
Document what you just configured:
RBAC ASSIGNMENT MATRIX═════════════════════════════════════════════════════════════
┌──────────────────────┬──────────┬─────────┬──────┐
│ Group │ Dev │ Staging │ Prod │
├──────────────────────┼──────────┼─────────┼──────┤
│ Junior Developers │ Contrib │ Reader │ Read │
│ Senior Developers │ Contrib │ Contrib │ Read │
│ DevOps Engineers │ Contrib │ Contrib │ Cont │
└──────────────────────┴──────────┴─────────┴──────┘
Legend: Contrib = Contributor, Read = Reader, Cont = Contributor
RESULT:
├─ Dev: Everyone has full access (playground)
├─ Staging: Seniors + DevOps can modify, juniors observe
└─ Prod: Only DevOps can modify, everyone else read-only
✅ Complete: Environment-based RBAC implemented
✅ Junior devs have different access in each environment
✅ DevOps is only one with Prod Contributor access
✅ All assignments documented
Policies provide safety guardrails - prevent dangerous operations even if someone tries to do them.
Step 1: Create Dev Policies (Minimal)
Dev is a sandbox - allow anything:
Step 2: Create Staging Policies (Moderate)
Staging needs to match Prod characteristics:
Policy 1: Require backup tag
Name: Require-Backup-Tag-StagingEffect: Deny
Condition: Resources without tag "backup" = "enabled"
Result: Cannot create resources without backup tag
Reason: Staging must be recoverable
Policy 2: Enforce encryption
Name: Require-Encryption-StagingEffect: Modify (auto-enable)
Condition: Storage accounts without encryption
Result: Auto-enables encryption if missing
Reason: Prepare for Prod's encryption requirement
Step 3: Create Prod Policies (Strict)
Production needs maximum protection:
Policy 1: Deny resource deletion
Name: Deny-Dangerous-Deletes-ProdEffect: Deny
Conditions:
├─ Deny deletion of Virtual Machines
├─ Deny deletion of SQL Databases
├─ Deny deletion of Storage Accounts
└─ Deny deletion of Key Vaults
Exceptions: DevOps group only (requires override)
Result: Accidental deletion impossible
Policy 2: Require backup tags
Name: Require-Backup-Tag-ProdEffect: Deny
Condition: Resources without tag "backup" = "enabled"
Result: Cannot deploy without backup protection
Policy 3: Enforce encryption
Name: Enforce-Encryption-ProdEffect: Modify
Conditions:
├─ Auto-enable storage account encryption
├─ Auto-enable disk encryption on VMs
└─ Auto-enable database encryption
Result: All Prod data encrypted by default
Policy 4: Require premium VM types
Name: Limit-VM-Types-ProdEffect: Deny
Condition: Deny non-premium VM sizes
Allowed: Standard</em>D2s<em>v3, Standard</em>D4s<em>v3, Standard</em>D8s<em>v3
Result: Prevent slow VMs in production
Policy 5: Enforce region restriction
Name: Prod-US-Regions-OnlyEffect: Deny
Condition: Deny resources outside US regions
Allowed regions: eastus, eastus2, westus, westus2
Result: Keep customer data in US (compliance)
Step 4: Document Policies
POLICY ENFORCEMENT BY ENVIRONMENT════════════════════════════════════════════════════════════
DEV SUBSCRIPTION:
├─ Policies: None (experimental environment)
├─ Philosophy: Fail fast, learn from mistakes
└─ Result: Junior devs can try anything
STAGING SUBSCRIPTION:
├─ Policy: Require backup tag
├─ Policy: Enforce encryption (auto-enable)
└─ Result: Staging mirrors Prod safety
PROD SUBSCRIPTION:
├─ Policy: Deny dangerous deletes (VM, DB, storage)
├─ Policy: Require backup tag
├─ Policy: Enforce encryption
├─ Policy: Premium VM types only
├─ Policy: US regions only
└─ Result: Production protected from common mistakes
✅ Complete: Policies prevent dangerous operations
✅ Staging has moderate policies
✅ Prod has strict protective policies
✅ All policies documented
Verify that access control actually works. Don't trust configuration - test it!
Step 1: Test Junior Developer Access
Simulate a junior developer signing in:
TEST SCENARIO: Junior dev trying to access each environmentOption 1: Use a test junior dev account
├─ Sign in as junior developer user
├─ Navigate to each subscription
└─ Record what you see
Option 2: Use Access Control (IAM) > "Check access"
├─ Go to each subscription
├─ Click Check access
├─ Enter junior dev user name
└─ View what they can access
Expected Results:
Dev Subscription:├─ Can see: All resources ✓
├─ Can create: Resources ✓
├─ Can delete: Resources ✓
└─ Result: PASS ✓
Staging Subscription:
├─ Can see: All resources ✓
├─ Can create: Resources ✗ (Denied - Reader role)
├─ Can delete: Resources ✗ (Denied - Reader role)
└─ Result: PASS ✓
Prod Subscription:
├─ Can see: All resources ✓
├─ Can create: Resources ✗ (Denied - Reader role)
├─ Can delete: Resources ✗ (Denied - Reader role)
└─ Result: PASS ✓
Document results:
Junior Developer Access Test: </em><strong> PASS ✓ </strong><em> FAIL ✗Expected: Full in Dev, Read-only in Staging/Prod
Actual: [Your results]
Step 2: Test Senior Developer Access
TEST SCENARIO: Senior dev accessing all environmentsExpected Results:
Dev: Contributor (create, modify, delete) ✓
Staging: Contributor (create, modify, delete) ✓
Prod: Reader (view only, cannot modify) ✓
Verification Method:
├─ Check access for senior dev in IAM
└─ Record findings
Step 3: Test DevOps Engineer Access
TEST SCENARIO: DevOps engineer deploying to all environmentsExpected Results:
Dev: Contributor ✓
Staging: Contributor ✓
Prod: Contributor (can deploy) ✓
Verification: DevOps should have full access everywhere
Step 4: Create Access Test Report
ACCESS CONTROL TEST REPORT════════════════════════════════════════════════════════════
Test Date: </em>___________<em><strong>
Tester: </strong></em>_________<em><strong>
GROUP: Junior Developers
├─ Dev Access: PASS ✓ / FAIL ✗
├─ Staging Access: PASS ✓ / FAIL ✗
└─ Prod Access: PASS ✓ / FAIL ✗
GROUP: Senior Developers
├─ Dev Access: PASS ✓ / FAIL ✗
├─ Staging Access: PASS ✓ / FAIL ✗
└─ Prod Access: PASS ✓ / FAIL ✗
GROUP: DevOps Engineers
├─ Dev Access: PASS ✓ / FAIL ✗
├─ Staging Access: PASS ✓ / FAIL ✗
└─ Prod Access: PASS ✓ / FAIL ✗
OVERALL: ALL PASS ✓ / SOME FAIL ✗
✅ Complete: All access controls verified working
✅ Junior devs: Full in Dev, read-only elsewhere
✅ Senior devs: Contributor in Dev/Staging, read-only in Prod
✅ DevOps: Full access all environments
Policies only work if they actually stop dangerous operations. Test them!
Step 1: Test Prod Policy - Deny VM Deletion
Attempt to delete a VM in Prod (should be blocked):
- Go to Prod Subscription > Virtual Machines > [VM]
- Click Delete
- Expected: Policy blocks deletion with message
Expected Denial Message:
Policy denied this operation:Name: Deny-Dangerous-Deletes-Prod
Effect: VM deletion denied in Prod
Reason: Production safety guardrail
To override:
├─ Must be DevOps engineer
├─ Must have override permissions
└─ Deletion tracked in audit logs
Document result:
Policy Test: VM Deletion in Prod├─ Attempted: Delete VM
├─ Expected: Denied by policy
├─ Actual: </strong></em> Denied ✓ <em><strong> Allowed ✗
├─ Message: </strong></em>_________<em><strong>
└─ Result: PASS ✓ / FAIL ✗
Step 2: Test Prod Policy - Backup Tag Requirement
Attempt to create a resource without backup tag (should be denied):
- Expected: Policy denies creation
Document result:
Policy Test: Missing Backup Tag in Prod├─ Attempted: Create storage without backup tag
├─ Expected: Denied
├─ Actual: </strong></em> Denied ✓ <em><strong> Allowed ✗
└─ Result: PASS ✓ / FAIL ✗
Step 3: Test Policy Enforcement Success
Create a resource WITH all required tags (should succeed):
- Name: test-storage-[timestamp]
- Add tags: backup=enabled
Document result:
Policy Test: Resource with Required Tags├─ Created: Storage account with backup tag
├─ Expected: Success
├─ Actual: </strong></em> Success ✓ <em><strong> Denied ✗
└─ Result: PASS ✓ / FAIL ✗
Step 4: Create Policy Verification Report
POLICY VERIFICATION REPORT════════════════════════════════════════════════════════════
DENIAL TESTS (Verify policies block dangerous operations)
├─ Deny VM Deletion: PASS ✓ / FAIL ✗
├─ Deny DB Deletion: PASS ✓ / FAIL ✗
├─ Deny Untagged Resources: PASS ✓ / FAIL ✗
└─ Overall Denial Tests: </strong></em> All Pass <em><strong> Some Fail
ENFORCEMENT TESTS (Verify creation with proper tags succeeds)
├─ Storage with backup tag: PASS ✓ / FAIL ✗
├─ VM with encryption: PASS ✓ / FAIL ✗
└─ Overall Enforcement: </strong></em> All Pass <em><strong> Some Fail
CONCLUSION:
Policies are: </strong></em> Working Correctly <em><strong> Need Adjustment
✅ Complete: All policy tests performed
✅ Policies successfully block dangerous operations
✅ Compliant resources can be created
✅ Audit trail shows enforcement
After completing all 5 parts, verify everything is in place:
ENVIRONMENT SEGREGATION FINAL CHECKLIST════════════════════════════════════════════════════════════
SUBSCRIPTIONS & GROUPS
├─ [ ] 3 subscriptions (Dev, Staging, Prod) created
├─ [ ] 4 Entra groups created
├─ [ ] Groups populated with test members
└─ [ ] All documented
RBAC CONFIGURATION
├─ [ ] Dev: All groups = Contributor
├─ [ ] Staging: Juniors=Reader, Seniors+DevOps=Contributor
├─ [ ] Prod: Juniors+Seniors=Reader, DevOps=Contributor
└─ [ ] All assignments verified in IAM
POLICIES
├─ [ ] Dev: No mandatory policies (sandbox)
├─ [ ] Staging: Backup tag + encryption policies
├─ [ ] Prod: 5 strict policies (deny deletes, require tags, etc.)
└─ [ ] All policies tested and verified
ACCESS TESTING
├─ [ ] Junior dev: Full→Read→Read (Dev→Staging→Prod) ✓
├─ [ ] Senior dev: Full→Full→Read (Dev→Staging→Prod) ✓
├─ [ ] DevOps: Full→Full→Full (all environments) ✓
└─ [ ] All tests documented
POLICY ENFORCEMENT
├─ [ ] Attempted VM deletion in Prod: Denied ✓
├─ [ ] Attempted resource without tags: Denied ✓
├─ [ ] Created resource with proper tags: Success ✓
└─ [ ] All policy tests documented
DOCUMENTATION
├─ [ ] Subscription IDs recorded
├─ [ ] RBAC matrix created
├─ [ ] Policy list documented
├─ [ ] Access test report completed
└─ [ ] All findings summarized
OVERALL COMPLETION: </strong></em> 100% ___ Partial (identify gaps)
✅ Environment isolation prevents production incidents - Different access per environment catches mistakes before they reach customers
✅ RBAC enforces role-based access - Junior devs can't accidentally touch Prod
✅ Policies provide safety guardrails - Even if someone bypasses RBAC, policies protect critical resources
✅ Three-tier approach scales - Dev/Staging/Prod is the industry standard
✅ Testing is critical - Don't assume RBAC works, verify it
You've now implemented the pattern used by: