Homeβ€ΊπŸ” Phase 1: Set Up Access & Data Architectureβ€ΊModule 97 min read Β· 10/25

Putting It All Together: Complete Architecture

Reference

Putting It All Together: The Complete Access Architecture

You've learned the three concepts that replace management zones. Now let's see how they work together in a real enterprise deployment. This module walks through a complete architecture for a company with 5 teams across 4 environments.

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         DYNATRACE ACCOUNT                                    β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  DATA PARTITIONING (Buckets)                                         β”‚    β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚    β”‚
β”‚  β”‚  β”‚ hot_ops  β”‚ β”‚ standard β”‚ β”‚ analyticsβ”‚ β”‚complianceβ”‚ β”‚  debug   β”‚ β”‚    β”‚
β”‚  β”‚  β”‚  7 days  β”‚ β”‚ 35 days  β”‚ β”‚ 90 days  β”‚ β”‚ 365 days β”‚ β”‚  3 days  β”‚ β”‚    β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  DATA ACCESS (IAM/ABAC)                                              β”‚    β”‚
β”‚  β”‚                                                                       β”‚    β”‚
β”‚  β”‚  Groups:     SV-PAY.PRD.Analyst  SV-PLAT.PRD.Admin  SV-SEC.PRD.Ops  β”‚    β”‚
β”‚  β”‚  Policies:   Read data           Full access         Security data    β”‚    β”‚
β”‚  β”‚  Boundaries: dt.security_context MATCH ("SV-PAY.PRD")                β”‚    β”‚
β”‚  β”‚              dt.security_context MATCH ("SV-PLAT.PRD")               β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  DATA SEGMENTATION (Segments)                                        β”‚    β”‚
β”‚  β”‚                                                                       β”‚    β”‚
β”‚  β”‚  "Production"     β†’ matchesValue(tags, "env:production")             β”‚    β”‚
β”‚  β”‚  "Team Payments"  β†’ dt.security_context == "SV-PAY.PRD"             β”‚    β”‚
β”‚  β”‚  "Hot Logs"       β†’ dt.system.bucket == "hot_ops"                    β”‚    β”‚
β”‚  β”‚  "K8s Cluster A"  β†’ k8s.cluster.name == "prod-east"                 β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

How They Interact

Concept              Controls                    Enforced At
───────────────────  ──────────────────────────  ──────────────────────────
Buckets              WHERE data lives, HOW LONG  Ingest time (OpenPipeline)
IAM/ABAC             WHO can see WHAT data       Query time (Grail engine)
Segments             HOW users FILTER data       Query time (UI/dashboard)

Key insight: they're independent but complementary:

  • A user might have ABAC access to all payment data (IAM)
  • But only see production data in their dashboard (Segment filter)
  • And that data lives in a 35-day bucket (Partitioning)

Real-World Example: Banking Customer

The Setup

Teams:        5 (Payments, Platform, Security, Mobile, Data)
Environments: 4 (DEV, TST, UAT, PRD)
Hosts:        200+ VMs + 3 K8s clusters
Services:     500+ auto-detected

Bucket Design

Bucket                  Retention  Routing Rule                        Teams
──────────────────────  ─────────  ──────────────────────────────────  ──────────
prod_hot                7 days     env=PRD AND (ERROR OR WARN)         All (ops)
prod_standard           35 days    env=PRD AND INFO                    All
nonprod_standard        14 days    env=DEV|TST|UAT                     All
compliance_audit        365 days   matchesPhrase(content, "audit")     Security
debug_verbose           3 days     loglevel=DEBUG                      Developers

IAM Design (V3.1 Model)

Per team (5 teams Γ— 4 envs = 20 groups):
  SV-PAYMENTS.DEV.Analyst    β†’ boundary: dt.security_context MATCH ("SV-PAYMENTS.DEV")
  SV-PAYMENTS.TST.Analyst    β†’ boundary: dt.security_context MATCH ("SV-PAYMENTS.TST")
  SV-PAYMENTS.UAT.Analyst    β†’ boundary: dt.security_context MATCH ("SV-PAYMENTS.UAT")
  SV-PAYMENTS.PRD.Analyst    β†’ boundary: dt.security_context MATCH ("SV-PAYMENTS.PRD")

Cross-team roles:
  PLATFORM.ALL.Admin         β†’ boundary: (none β€” platform team sees everything)
  SECURITY.ALL.Auditor       β†’ boundary: bucket == "compliance_audit"

Segment Design

Segment Name         Filter                                    Used By
───────────────────  ──────────────────────────────────────── ──────────────────
Production           matchesValue(tags, "env:production")       All dashboards
Non-Production       NOT matchesValue(tags, "env:production")   Dev dashboards
Team Payments        dt.security_context == "SV-PAYMENTS.PRD"   Team dashboards
K8s Cluster East     k8s.cluster.name == "prod-east"            Infra dashboards
Hot Issues           dt.system.bucket == "prod_hot"             Ops dashboards

Enrichment Strategy

Infrastructure       Method                          Tag Value
───────────────────  ──────────────────────────────  ──────────────────────────
200 VMs              oneagentctl --set-host-tag      dt.security_context=SV-XXX.ENV
K8s cluster 1        Namespace label enrichment      dt.security_context from label
K8s cluster 2        Namespace label enrichment      dt.security_context from label
K8s cluster 3        Namespace label enrichment      dt.security_context from label
SNMP devices         Extension topology dimension    dt.security_context in config
External syslog      OpenPipeline enrichment         Match source IP β†’ add context

The Onboarding Workflow (New Team)

When a new team joins, here's what gets created:

Step  Action                                  Terraform Resource
────  ──────────────────────────────────────  ──────────────────────────────────
1     Create 4 groups (DEV/TST/UAT/PRD)       dynatrace_iam_group Γ— 4
2     Create Gen3 boundaries (4)              dynatrace_iam_policy_boundary Γ— 4
3     Create Classic boundaries (4)           dynatrace_iam_policy_boundary Γ— 4
4     Bind policies with boundaries (4)       dynatrace_iam_policy_bindings_v2 Γ— 4
5     Set host properties (security context)  oneagentctl --set-host-property (Ansible)
6     Add K8s namespace labels                kubectl label namespace
7     Configure K8s enrichment rules          dynatrace_kubernetes_enrichment
8     Verify entity security context          dynatrace_grail_security_context (if override needed)
9     Create team segment                     Segments API / Monaco

Total: 16 Terraform resources + host property setup + K8s labels + enrichment rule + segment

Complete Terraform Resource List

Resource                              Auth     Purpose
────────────────────────────────────  ───────  ──────────────────────────────────────
dynatrace_iam_group                   OAuth    Create team groups
dynatrace_iam_policy_boundary         OAuth    Create Gen3 + Classic boundaries
dynatrace_iam_policy_bindings_v2      OAuth    Bind policies with per-policy boundaries
dynatrace_iam_policy                  OAuth    Custom policies (if defaults insufficient)
dynatrace_kubernetes_enrichment       Token    Map K8s labels β†’ dt.security_context
dynatrace_grail_security_context      Token    Override entity security context source
dynatrace_openpipeline_v2_*           OAuth    Security context processors for external data

πŸ’‘ This is fully automatable. The V3.1 Terraform template takes a service code and creates all 16 resources. Host tagging can be scripted via Ansible. K8s labels are in your namespace YAML. One terraform apply + one Ansible playbook = team onboarded.

The Offboarding Workflow (Team Leaves)

Step  Action                                  Risk
────  ──────────────────────────────────────  ──────────────────────────────────
1     Remove users from groups                 Immediate access revocation
2     (Optional) Delete groups                 Clean up IAM
3     Keep boundaries (data still exists)      Data remains queryable by admins
4     Keep bucket routing (data still flows)   No data loss
5     Update segments if team-specific         Remove from shared dashboards

⚠️ Never delete boundaries before confirming no other groups reference them. Boundaries are reusable β€” another team might share the same boundary for cross-team access.

Common Architecture Mistakes

Mistake                                 Consequence                          Fix
──────────────────────────────────────  ───────────────────────────────────  ──────────────────────────
Skip enrichment, enable ABAC            Users see zero data                  Tag first, restrict second
One boundary per team (no env split)    Dev team sees prod data              Use SV-XXX.ENV pattern
Custom policies instead of defaults     Policies break on platform updates   Use defaults + boundaries
Forget classic boundary                 Users can't access classic apps      Dual boundaries during migration
Route before enrich in OpenPipeline     Can't route on enriched fields       Route on ingest-time fields
Conditional DENY on Grail tables        Executes as UNCONDITIONAL DENY       Never use conditional DENY
Multiple boundaries with mixed scopes   Unintended unconditional access      Use dt.security_context (applies to all)
Use --set-host-tag for security ctx     Data not tagged (wrong command)      Use --set-host-property
Pod annotations for K8s enrichment      Missing K8s metrics/events/entities  Use namespace labels + enrichment rules
More than 10 conditions in boundary     API rejects it                       Split into multiple boundaries

Architecture Decision Record

Document these decisions for your customer:

Decision                    Options                          Recommendation
──────────────────────────  ───────────────────────────────  ──────────────────────────
Naming convention           Flat vs hierarchical             Hierarchical: SV-CODE.ENV
Boundary granularity        Per-team vs per-team-per-env     Per-team-per-env (V3.1)
Policy approach             Custom vs default + boundary     Default + boundary
Bucket strategy             Per-team vs per-retention-tier   Per-retention-tier (simpler)
Enrichment method           Host tags vs auto-tagging        Host tags (explicit, reliable)
Segment ownership           Central vs team-managed          Central (governance)
Classic boundary lifetime   Keep forever vs deprecate        Deprecate after full migration

Validation Queries

After deploying the architecture, validate with these DQL queries:

// 1. Check all hosts are tagged
fetch dt.entity.host
| fields entity.name, tags
| filter NOT matchesValue(tags, "dt.security_context:*")
// Result should be EMPTY (all hosts tagged)

// 2. Check data isolation works
// Run as SV-PAYMENTS.PRD.Analyst user:
fetch logs, from:now()-1h
| summarize count(), by:{dt.security_context}
// Should ONLY show SV-PAYMENTS.PRD records

// 3. Check bucket routing is working
fetch logs, from:now()-1h
| summarize count(), by:{dt.system.bucket}
// Should show distribution across your buckets

// 4. Check for untagged data (ABAC gaps)
fetch logs, from:now()-1h
| filter isNull(dt.security_context)
| summarize cnt=count(), by:{log.source}
| sort cnt desc
// These sources need enrichment rules
πŸ“ Knowledge Check

Q: A customer asks: "Can we use one bucket per team instead of one bucket per retention tier?" What's your advice?

A: Per-retention-tier is usually better. Reasons: (1) fewer buckets to manage (5 vs 50), (2) ABAC already handles team isolation via security context, (3) bucket-per-team creates operational overhead when teams merge/split. Use buckets for retention strategy, ABAC for access control.

Q: The platform team needs to see ALL data across all teams. How do you set this up?

A: Create a group with NO boundary on the data read policy. Or use a boundary with a broad MATCH pattern like MATCH ("SV-") that matches all service codes. The platform team's role policy grants full read access without restriction.

Q: After migration, when can you remove the classic boundaries?

A: When ALL users have migrated to Gen3 apps and no one uses classic UI screens that rely on management zones. In practice, this is 3-6 months after go-live. Keep classic boundaries during the transition period β€” they cost nothing.

Q: A new microservice is deployed but its data isn't showing up for the team. What's wrong?

A: Most likely the K8s namespace doesn't have the security context label, or the host doesn't have the tag set. Check: fetch logs | filter dt.source_entity == "SERVICE-XXXXX" | fields dt.security_context | limit 1. If null, the enrichment is missing.