Reader Access: Architecture, Patterns & Options¶
Reader access in cloud platforms is frequently mischaracterized as a low-risk, trivial permission. In an enterprise landing zone aligned with Microsoft CAF, the Enterprise Access Model (EAM), and NIST SP 800-53, reader access is a multi-dimensional architecture decision: balancing reconnaissance risk against operational visibility, distinguishing control-plane metadata from data-plane secrets, selecting the optimal inheritance scope, and choosing between standing GitOps grants and just-in-time (JIT) PIM activation.
- GRINNTEC: Platform Engineering
- GRINNTEC: Platform Identity & RBAC
- GRINNTEC: Access Tiering Model: EAM, NIST and Tier 0/1/2
- GRINNTEC: Azure RBAC by Management Group
- GRINNTEC: Subscription Vending
- Microsoft CAF — Azure landing zone identity and access
- Microsoft Entra Enterprise Access Model (EAM)
The Core Fundamentals¶
Before designing reader access, cloud architects must recognize three core security and architectural realities:
1. Control Plane (ARM) vs. Data Plane Isolation¶
In Azure, permissions are strictly bifurcated between the Management/Control Plane (Azure Resource Manager - ARM) and the Data Plane:
graph LR
subgraph "Control Plane (ARM API)"
ARM[Azure Resource Manager]
ROLE_R["Built-in 'Reader'"]
ARM --> ROLE_R
ROLE_R --> MD1["Resource Configurations & SKU"]
ROLE_R --> MD2["Virtual Network Topology & IP rules"]
ROLE_R --> MD3["Tags, Metrics & Diagnostic Settings"]
end
subgraph "Data Plane (Resource Service APIs)"
DP[Data Endpoints]
ROLE_DPR["Data Plane Roles<br/>(e.g., Storage Blob Data Reader)"]
DP --> ROLE_DPR
ROLE_DPR --> D1["Storage Blobs & Files"]
ROLE_DPR --> D2["Key Vault Secret & Key Values"]
ROLE_DPR --> D3["SQL & Cosmos DB Table Rows"]
end
ROLE_R -.->|NO ACCESS| DP
- Built-in
Readerpermits inspection of ARM metadata: resource types, IDs, SKUs, networking associations, tags, and diagnostic settings. - Built-in
Readerstrictly CANNOT read data payloads: it cannot view the secret strings in Key Vault, read blobs in a storage container, query rows in Azure SQL or Cosmos DB, or receive messages from a Service Bus queue. - Architectural implication: An auditor or engineer holding
Readercan verify infrastructure posture, encryption configurations, and logging coverage without gaining exposure to sensitive business data or credentials.
2. The "Mechanism vs. Capability" Paradox¶
Per Microsoft's Enterprise Access Model (EAM), we must separate the capability a role grants from the mechanism required to assign it:
- Capability: The
Readerrole is non-destructive (Tier 2 / Data & Workload plane). A user holding it cannot alter configurations or destroy resources. - Mechanism: Provisioning a
Readerrole assignment at the Tenant Root Group (/) or Intermediate Root (mg-grinntec) requiresOwnerorUser Access Administratorat that top-level scope. That mechanism is Tier 0 / Control Plane. - Consequently, while the resulting read access is low privilege, the pipeline or identity that creates that assignment must be governed with Tier 0 controls (see Tier 0 Pipeline Design).
3. Reconnaissance & Information Disclosure Risks¶
While read access cannot directly modify or delete assets, unconstrained estate-wide read access introduces significant reconnaissance risk: - It reveals internal subnet IP addresses, firewall rules, and virtual network peerings. - It exposes resource naming patterns, subscription IDs, and tenant hierarchy topologies. - It permits an adversary who compromises a reader account to map out high-value targets, security monitoring gaps, and potential attack paths before attempting privilege escalation.
Scoping & Hierarchy Options (Where to Assign)¶
Azure RBAC inherits downward through the management hierarchy: Management Group → Subscription → Resource Group → Resource. Selecting where reader access is anchored determines both its blast radius and its operational overhead.
graph TD
ROOT["Tenant Root Group (/)<br/>Option 1: Extreme breadth (rarely used)"]
MG_INT["mg-grinntec (Intermediate Root)<br/>Option 1: Estate-Wide Central Reader (grp-tenant-readonly)"]
MG_PLAT["mg-platform<br/>Option 2: Platform Ops Reader"]
MG_LZ["mg-landingzones<br/>Option 2: Workload Archetype Reader"]
MG_SB["mg-sandboxes<br/>Option 2: Sandbox Reader"]
SUB_PROD["Subscription: gt-mkdocs-prod-westeu<br/>Option 3: Per-Sub Reader (grp-gt-mkdocs-prod-westeu-reader)"]
RG_STATE["Resource Group: rg-terraform-state<br/>Option 4: Scoped Component Reader (sp-*-ro)"]
ROOT --> MG_INT
MG_INT --> MG_PLAT
MG_INT --> MG_LZ
MG_INT --> MG_SB
MG_LZ --> SUB_PROD
SUB_PROD --> RG_STATE
Option 1: Estate-Wide at Intermediate Root (mg-grinntec)¶
Assigning Reader once at the intermediate root management group (mg-grinntec) automatically inherits downward to every current subscription and any future subscription created by the vending factory.
- Target Personas: Central CISO audit teams, Enterprise Architects, Central FinOps (using Cost Management Reader), and Cloud Center of Excellence (CCoE) leads.
- Implementation: Entra ID group
grp-tenant-readonlyassigned built-inReaderatmg-grinntecviaazure-platform-identity. - Advantages: Zero operational touch when vending new subscriptions; complete, unbroken estate visibility.
- Trade-offs: Broadest possible reconnaissance surface; exposes sandbox experiments, production workloads, and core networking simultaneously.
Option 2: Archetype Management Group Scoping (mg-platform vs mg-landingzones)¶
Instead of granting estate-wide visibility at the root, role assignments are placed at archetype branch management groups:
- Readers assigned at mg-landingzones see all workload subscriptions, but have zero visibility into mg-platform (hub networking, central firewalls, shared state backends).
- Readers assigned at mg-platform see foundational infrastructure without exposing application payloads or workload subscriptions.
- Target Personas: Domain architects, platform infrastructure reviewers, business-unit security leads.
- Advantages: Enforces separation of concerns between shared platform services and application workloads.
- Trade-offs: Requires multiple group assignments (one per branch) rather than a single root assignment.
Option 3: Per-Subscription Vended Groups (grp-{sub}-reader)¶
Every subscription provisioned by Grinntec's subscription vending engine automatically receives its own dedicated Entra ID security group: grp-{subscription_name}-reader. This group is bound to the built-in Reader role at that specific subscription scope only.
- Target Personas: Application developers, workload QA teams, subscription-specific compliance reviewers, and third-party vendor auditors.
- Implementation: Declared in the subscription bootstrap module call via
rbac.reader: - Advantages: Absolute workload boundary isolation; application teams can inspect their full deployment without seeing adjacent services or platform hubs.
- Trade-offs: Higher group count in Entra ID (1 reader group per subscription).
Option 4: Resource Group or Component Scoping¶
Role assignments are placed directly on a targeted Resource Group (e.g., rg-terraform-state or rg-hub-networking) or on individual resources.
- Target Personas: Automation service principals and specialized diagnostic tools.
- Implementation: Commonly used for CI/CD plan identities:
- Advantages: Strict least privilege; permits ARM metadata inspection (e.g.,
terraform initvalidating storage account configuration) without subscription-wide visibility. - Trade-offs: Cannot be handled entirely through generic management group inheritance; requires component-level Terraform declaration.
Option 5: The Hybrid Group Nesting Pattern (Grinntec Standard)¶
To avoid managing thousands of direct user assignments across hundreds of subscriptions, Grinntec combines management group assignments with group nesting:
graph TD
CENTRAL["Central Entra Group<br/>(e.g., grp-finops-readers)"]
SUB_GRP["Vended Subscription Group<br/>(grp-gt-mkdocs-prod-westeu-reader)"]
USER["Individual User UPN<br/>(e.g., tim.burgess@grinntec.net)"]
SUB["Subscription Scope<br/>Role: Reader"]
CENTRAL -->|Nested Member via subscription-memberships.tf| SUB_GRP
USER -->|Direct Member via rbac variable| SUB_GRP
SUB_GRP -->|azurerm_role_assignment| SUB
- Platform-wide groups (
grp-platform-engineers,grp-finops-readers) can be nested directly into per-subscription reader groups usingsubscription-memberships.tf. - Subscription vending modules can accept external group IDs via
reader_group_ids. - Result: Central teams gain automatic access through existing per-subscription group infrastructure without altering the subscription's internal RBAC definitions.
Role Specialization Options (What to Assign)¶
Assigning generic Reader everywhere often violates NIST AC-6 (Least Privilege) when the user only requires a specific slice of information. Azure provides specialized built-in reader roles that should be selected based on the persona:
| Built-In Role | Primary Scope | Capabilities Granted | Capabilities Denied | Ideal Persona |
|---|---|---|---|---|
| Reader | MG, Sub, RG | Views all ARM resource configurations, tags, deployment history, topology | Cannot read data-plane payloads (blobs, secrets, DB rows) | Developers, Architects, General Auditors |
| Cost Management Reader | MG or Sub | Views billing accounts, invoices, cost analysis, budget thresholds, reservation recommendations | Cannot view resource configurations, networking, or ARM resource blades | FinOps, Finance, Procurement |
| Monitoring Reader | MG, Sub, RG | Views Azure Monitor metrics, alert rules, diagnostic settings, Log Analytics workspaces, workbooks | Cannot inspect underlying application code or sensitive resource configurations | SRE, NOC Engineers, Dashboard Tools |
| Security Reader | Tenant, MG, Sub | Views Microsoft Defender for Cloud alerts, secure scores, regulatory compliance maps, vulnerability assessments | Cannot modify security policies or remediate recommendations | SOC Tier 1, Security Compliance Officers |
| Key Vault Reader | RG or Key Vault | Reads Key Vault resource metadata (network ACLs, tags, diagnostics) | Cannot view, read, or export the actual secret, key, or certificate values | Cloud Governance & Vault Infrastructure Auditors |
| Storage Blob Data Reader | Storage Account or Container | Data-Plane Role: Reads, downloads, and lists blobs inside storage containers | Cannot modify storage account ARM properties | Data Analysts, Backup Verifiers |
Principle of Least Privilege: FinOps vs. Engineering
Do not assign generic Reader to the finance team. Assign Cost Management Reader at mg-grinntec. This gives full cost visibility across all current and future subscriptions while preventing non-technical teams from inadvertently inspecting resource topologies or security settings.
Access Governance & Activation Models (How Access is Granted)¶
How reader access is held and delivered determines the organisation's exposure to credential theft and lateral movement:
graph LR
subgraph "Model A: Standing GitOps"
MR_A[GitLab MR] --> TF_A[Terraform Apply] --> GRP_A[Standing Group Membership]
end
subgraph "Model B: Just-In-Time (PIM)"
USER_B[User Request] --> PIM_B[Entra PIM Activation<br/>MFA + Justification] --> TIME_B[Time-Bound Role<br/>(4 to 8 Hours)]
end
subgraph "Model C: Machine Identity"
OIDC_C[GitLab OIDC] --> SP_C[sp-*-ro Service Principal] --> PLAN_C[Plan-Only Pipeline]
end
Model A: Standing GitOps-Managed Groups (Continuous Access)¶
- How it works: Members are declared as UPN lists in Terraform (
azure-platform-identityorazure-subscriptions). Changes require a Merge Request, peer review, and CI apply. - When to use: Day-to-day workload developers who continuously monitor application infrastructure; FinOps automated cost ingestors.
- Controls: Protected branch rules, mandatory code reviews, automated CI syntax validation.
Model B: Just-In-Time (JIT) via Entra Privileged Identity Management (PIM)¶
- How it works: Users do not hold standing Reader access. Instead, they are provisioned as Eligible in Entra PIM for Azure Resources. When an audit or investigation is needed, the user activates the role via the Azure portal or CLI for a time-bounded window (e.g., 4 or 8 hours) requiring MFA, business justification, and optional peer approval.
- When to use:
- Read access to Production subscriptions (
mg-online,gt-mkdocs-prod-westeu). - Read access to Central Management / Logging (
mg-management, hosting central Log Analytics and audit trails). - External third-party auditors or contractors.
- Controls: Aligns with NIST AC-2(6) (Dynamic Privilege Management) and NIST AC-6(5) (Privileged Accounts), eliminating permanent discovery footprints.
Access reviews apply on top of Models A and B
Access reviews are not a separate way of granting access. They are a control that applies to access however it was granted. A scheduled Entra ID access review asks group owners or managers to confirm that each reader still needs access, and removes anyone who doesn't. Compliance frameworks such as SOC 2, ISO 27001 and PCI-DSS expect this, to stop orphaned accounts and access creep.
Access reviews are not configured in the tenant yet. Reader access granted through the Read-Only @ Landing Zones access package expires after 90 days and must be requested again. Standing reader groups (Model A) are not reviewed at all today. See Access Reviews for the recommended scopes, frequencies and reviewers.
Model C: Machine Read-Only Pipelines (Workload Identity Federation)¶
- How it works: Automated CI/CD pipelines require read access to generate Terraform execution plans, run security scans (Trivy, Checkov), or verify posture.
- Design pattern: Under Grinntec's Dual-Lane delivery model, read-only service principals (
sp-pla-tf-*-ro) holdReaderat their respective management group or subscription and are authenticated strictly via passwordless OIDC federated tokens (no stored secrets).
Comparative Decision Matrix¶
Use this matrix to select the appropriate reader pattern for any project or team:
| Persona / Scenario | Recommended Scope | Role Definition | Delivery Model | Blast Radius | Overhead |
|---|---|---|---|---|---|
| Central CISO / Audit Lead | mg-grinntec |
Reader + Security Reader |
PIM Eligible (JIT) | Estate-wide (ARM metadata) | Low (1 central grant) |
| FinOps / Cost Analyst | mg-grinntec |
Cost Management Reader |
Standing (GitOps) | Financial data only | Low (1 central grant) |
| Platform Ops Engineer | mg-platform |
Reader |
Standing (GitOps) | Platform subscriptions | Low |
| Workload App Developer | Target Subscription | Reader |
Standing (GitOps) | Single subscription | Medium (1 group per sub) |
| Production Incident Responder | Production Subscription | Reader |
PIM Eligible (4h window) | Single production sub | Low (PIM managed) |
| External Security Auditor | Target MG or Sub | Reader |
PIM Eligible (Approved) | Strictly bounded | Low (Time-bound) |
| CI/CD Pull Request Runner | Target Sub or RG | Reader |
OIDC Machine Identity | Bounded to pipeline scope | Automated |
Grinntec Reference Implementation & Terraform Patterns¶
Here is how these options are implemented in Grinntec's codebase:
1. Estate-Wide Central Reader (azure-platform-identity)¶
Declared at the intermediate root management group mg-grinntec in grp-tenant-readonly.tf:
# azure-platform-identity/grp-tenant-readonly.tf
locals {
tenant_readonly_upns = toset([
"cerys.matthews@grinntec.net",
"damon.albarn@grinntec.net",
"jarvis.cocker@grinntec.net",
])
}
resource "azuread_group" "tenant_readonly" {
display_name = "grp-tenant-readonly"
security_enabled = true
mail_enabled = false
}
resource "azuread_group_member" "tenant_readonly" {
for_each = local.tenant_readonly_upns
group_object_id = azuread_group.tenant_readonly.object_id
member_object_id = data.azuread_user.users[each.key].object_id
}
resource "azurerm_role_assignment" "tenant_readonly" {
scope = data.azurerm_management_group.mg_grinntec.id
role_definition_name = "Reader"
principal_id = azuread_group.tenant_readonly.object_id
}
2. FinOps Role Specialization (azure-platform-identity)¶
Assigning Cost Management Reader instead of generic Reader:
# azure-platform-identity/grp-finops-readers.tf
resource "azurerm_role_assignment" "finops_reader" {
scope = data.azurerm_management_group.mg_grinntec.id
role_definition_name = "Cost Management Reader"
principal_id = azuread_group.finops_readers.object_id
}
3. Vended Per-Subscription Reader Group (azure-subscriptions)¶
Subscription factory automatically vending grp-{sub}-reader and binding it:
# azure-subscriptions/modules/subscription-bootstrap/main.tf
resource "azuread_group" "sub_reader" {
display_name = "grp-${var.subscription_name}-reader"
security_enabled = true
mail_enabled = false
}
resource "azurerm_role_assignment" "sub_reader" {
scope = "/subscriptions/${var.subscription_id}"
role_definition_name = "Reader"
principal_id = azuread_group.sub_reader.object_id
}
# Optional extra reader groups (e.g. centralized security readers)
resource "azurerm_role_assignment" "extra_readers" {
for_each = toset(var.reader_group_ids)
scope = "/subscriptions/${var.subscription_id}"
role_definition_name = "Reader"
principal_id = each.value
}
4. Group Nesting Pattern (azure-platform-identity)¶
Nesting central groups into per-subscription groups without modifying subscription role assignments:
# azure-platform-identity/subscription-memberships.tf
locals {
subscriptions = {
"gt-mkdocs-prod-westeu" = {
contributor_groups = ["grp-platform-engineers"]
reader_groups = ["grp-finops-readers"]
}
}
}
resource "azuread_group_member" "sub_reader_nesting" {
for_each = {
for pair in local.subscription_reader_pairs : "${pair.sub}-${pair.group}" => pair
}
group_object_id = data.azuread_group.sub_reader_groups[each.value.sub].object_id
member_object_id = data.azuread_group.platform_groups[each.value.group].object_id
}
Architectural Recommendations¶
- Default to Role Specialization: Never assign generic
ReaderwhereCost Management ReaderorMonitoring Readerfulfills the requirement. - Isolate Workloads from Platform: For non-central personnel, restrict reader grants to
mg-landingzonesor the per-subscriptiongrp-{sub}-readergroup rather thanmg-grinntec. - Use PIM for Production and Sensitive Scopes: Enforce JIT activation with required business justification for any read access granted on production subscriptions or management groups hosting audit repositories (
mg-management). - Never conflate Control Plane with Data Plane: Explicitly document to audit and engineering teams that ARM
Readerdoes not grant access to Key Vault secrets or storage blob contents. If data access is legitimately needed, use dedicated data-plane roles subject to mandatory PIM approval.