Azure Cloud Architect End-to-end Azure-specific architecture: service selection, Well-Architected Framework assessment, identity and networking patterns, cost optimization, and operational defaults. Provider-specific complement to our generic skill — that one covers cross-cloud patterns; this one knows AKS pricing tiers, when to pick Cosmos over SQL DB, and how Front Door differs from Application Gateway. --- When to use this skill | Situation | Skill applies | |-----------|---------------| | Designing an Azure architecture from scratch | Yes — start with the service selection decision tree |…

+ format(l.monthly_usd, ',.0f'):>12}\")\n out.append(\"-\" * 72)\n total = sum(l.monthly_usd for l in lines)\n out.append(f\"{'TOTAL':\u003c28} {'':\u003c28} {'

Azure Cloud Architect End-to-end Azure-specific architecture: service selection, Well-Architected Framework assessment, identity and networking patterns, cost optimization, and operational defaults. Provider-specific complement to our generic skill — that one covers cross-cloud patterns; this one knows AKS pricing tiers, when to pick Cosmos over SQL DB, and how Front Door differs from Application Gateway. --- When to use this skill | Situation | Skill applies | |-----------|---------------| | Designing an Azure architecture from scratch | Yes — start with the service selection decision tree |…

+ format(total, ',.0f'):>12}\")\n out.append(\"\")\n if suggestions:\n out.append(\"Optimization opportunities:\")\n for s in suggestions:\n out.append(f\" {s}\")\n out.append(\"\")\n out.append(\"NOTE: Estimates are approximations using list prices. For procurement,\")\n out.append(\"always validate with Azure Pricing Calculator and apply reservations/discounts.\")\n return \"\\n\".join(out)\n\n\ndef parse_args() -> argparse.Namespace:\n p = argparse.ArgumentParser(\n description=\"Estimate Azure monthly cost from workload spec\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=__doc__,\n )\n p.add_argument(\"--workload-config\", required=True, help=\"Path to workload YAML spec\")\n p.add_argument(\"--format\", choices=[\"human\", \"json\"], default=\"human\")\n p.add_argument(\"--output\", help=\"Output file path\")\n return p.parse_args()\n\n\ndef main() -> int:\n args = parse_args()\n try:\n spec = parse_yaml(Path(args.workload_config).read_text())\n except OSError as e:\n print(f\"error: {e}\", file=sys.stderr)\n return 2\n lines, suggestions = estimate(spec)\n if args.format == \"json\":\n out = json.dumps(\n {\n \"lines\": [asdict(l) for l in lines],\n \"total_monthly_usd\": sum(l.monthly_usd for l in lines),\n \"suggestions\": suggestions,\n },\n indent=2,\n )\n else:\n out = render_human(lines, suggestions)\n if args.output:\n Path(args.output).write_text(out)\n print(f\"wrote {args.output}\", file=sys.stderr)\n else:\n print(out)\n return 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n","content_type":"text/x-python; charset=utf-8","language":"python","size":16568,"content_sha256":"d5e71018dfcd5832fd4936924d996e1d331ef7bb3f9153ac6df19b13a1b065ab"},{"filename":"scripts/azure_waf_scorer.py","content":"#!/usr/bin/env python3\n\"\"\"\nazure_waf_scorer.py — Score an Azure workload against the Well-Architected Framework.\n\nTakes a workload YAML spec and scores it against the 5 WAF pillars\n(Reliability, Security, Cost Optimization, Operational Excellence,\nPerformance Efficiency), 10 checks per pillar.\n\nOutputs per-pillar score 0-100, overall average, and findings sorted by severity.\n\nStdlib only. Markdown or JSON output.\n\nUsage:\n python3 azure_waf_scorer.py --workload-config workload.yaml\n python3 azure_waf_scorer.py --workload-config workload.yaml --format json\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport sys\nfrom dataclasses import dataclass, asdict, field\nfrom pathlib import Path\nfrom typing import Any\n\n\n# Reuse the same minimal YAML parser\ndef parse_yaml(text: str) -> dict[str, Any]:\n lines: list[tuple[int, str]] = []\n for raw in text.splitlines():\n line = raw.split(\"#\", 1)[0].rstrip()\n if not line.strip():\n continue\n indent = len(line) - len(line.lstrip(\" \"))\n lines.append((indent, line[indent:]))\n result, _ = _parse_block(lines, 0, 0)\n return result if isinstance(result, dict) else {}\n\n\ndef _parse_block(lines, idx, indent):\n if idx >= len(lines):\n return None, idx\n first_indent = lines[idx][0]\n if first_indent \u003c indent:\n return None, idx\n first_line = lines[idx][1]\n if first_line.startswith(\"- \"):\n return _parse_seq(lines, idx, first_indent)\n return _parse_map(lines, idx, first_indent)\n\n\ndef _parse_map(lines, idx, indent):\n out: dict[str, Any] = {}\n while idx \u003c len(lines):\n cur_indent, content = lines[idx]\n if cur_indent \u003c indent:\n break\n if cur_indent > indent:\n idx += 1\n continue\n if \":\" not in content:\n idx += 1\n continue\n key, _, rest = content.partition(\":\")\n key = key.strip().strip('\"').strip(\"'\")\n rest = rest.strip()\n if rest:\n out[key] = _scalar(rest)\n idx += 1\n else:\n idx += 1\n if idx \u003c len(lines) and lines[idx][0] > indent:\n value, idx = _parse_block(lines, idx, lines[idx][0])\n out[key] = value if value is not None else {}\n else:\n out[key] = {}\n return out, idx\n\n\ndef _parse_seq(lines, idx, indent):\n out: list[Any] = []\n while idx \u003c len(lines):\n cur_indent, content = lines[idx]\n if cur_indent \u003c indent:\n break\n if not content.startswith(\"- \"):\n break\n rest = content[2:].strip()\n if not rest:\n idx += 1\n if idx \u003c len(lines) and lines[idx][0] > indent:\n value, idx = _parse_block(lines, idx, lines[idx][0])\n out.append(value if value is not None else {})\n else:\n out.append(None)\n elif \":\" in rest:\n synth = [(indent + 2, rest)]\n j = idx + 1\n while j \u003c len(lines) and lines[j][0] > indent:\n synth.append(lines[j])\n j += 1\n value, _ = _parse_map(synth, 0, indent + 2)\n out.append(value)\n idx = j\n else:\n out.append(_scalar(rest))\n idx += 1\n return out, idx\n\n\ndef _scalar(s: str):\n s = s.strip()\n if s.startswith('\"') and s.endswith('\"'):\n return s[1:-1]\n if s.startswith(\"'\") and s.endswith(\"'\"):\n return s[1:-1]\n if s.lower() in (\"true\", \"yes\"):\n return True\n if s.lower() in (\"false\", \"no\"):\n return False\n if s.lower() in (\"null\", \"~\", \"\"):\n return None\n try:\n return int(s)\n except ValueError:\n pass\n try:\n return float(s)\n except ValueError:\n pass\n return s\n\n\n@dataclass\nclass Check:\n id: str\n pillar: str\n question: str\n severity: str # info=1, warning=2, critical=3\n pass_: bool\n detail: str\n recommendation: str\n\n\nSEVERITY_WEIGHT = {\"info\": 1, \"warning\": 2, \"critical\": 3}\n\n\ndef get(spec: dict[str, Any], path: str, default=None):\n keys = path.split(\".\")\n cur = spec\n for k in keys:\n if not isinstance(cur, dict):\n return default\n cur = cur.get(k, default if k == keys[-1] else {})\n return cur\n\n\ndef check_reliability(spec: dict[str, Any]) -> list[Check]:\n tier = spec.get(\"tier\", 2)\n cb = []\n cb.append(Check(\"R1\", \"Reliability\", \"Deployed across at least 2 AZs?\",\n \"critical\", bool(get(spec, \"compute.zone_redundant\")),\n f\"compute.zone_redundant={get(spec, 'compute.zone_redundant')}\",\n \"Enable zone-redundant tier on PaaS or deploy VMSS across zones.\"))\n cb.append(Check(\"R2\", \"Reliability\", \"RPO/RTO documented?\",\n \"critical\", bool(get(spec, \"reliability.rpo_minutes\")) and bool(get(spec, \"reliability.rto_minutes\")),\n f\"rpo={get(spec, 'reliability.rpo_minutes')}, rto={get(spec, 'reliability.rto_minutes')}\",\n \"Define RPO/RTO with business stakeholders and document.\"))\n cb.append(Check(\"R3\", \"Reliability\", \"Backups tested with restore drill?\",\n \"critical\", all(d.get(\"backup_tested\") for d in spec.get(\"data\", []) if isinstance(d, dict)),\n \"data services backup_tested status\",\n \"Schedule quarterly restore tests; untested backup is no backup.\"))\n cb.append(Check(\"R4\", \"Reliability\", \"Multi-region DR plan for tier-1?\",\n \"critical\" if tier == 1 else \"warning\",\n bool(get(spec, \"compute.multi_region\")),\n f\"multi_region={get(spec, 'compute.multi_region')}\",\n \"Document failover/failback runbook with regular DR tests.\"))\n cb.append(Check(\"R5\", \"Reliability\", \"Health probes configured?\",\n \"warning\", bool(get(spec, \"operations.health_probes\")),\n \"operations.health_probes\",\n \"Configure liveness + readiness probes; LBs need these to route safely.\"))\n cb.append(Check(\"R6\", \"Reliability\", \"Autoscaling enabled?\",\n \"warning\", bool(get(spec, \"compute.autoscale\")),\n f\"compute.autoscale={get(spec, 'compute.autoscale')}\",\n \"Configure autoscale based on actual load metrics.\"))\n cb.append(Check(\"R7\", \"Reliability\", \"Retry/circuit-breaker patterns in app code?\",\n \"warning\", bool(get(spec, \"operations.retry_policies\")),\n \"operations.retry_policies\",\n \"Use Polly / tenacity / similar — exponential backoff + max retries + circuit breaker.\"))\n cb.append(Check(\"R8\", \"Reliability\", \"Data services configured for HA?\",\n \"critical\", all(d.get(\"zone_redundant\") or d.get(\"ha\") for d in spec.get(\"data\", []) if isinstance(d, dict)),\n \"data zone_redundant or ha\",\n \"Enable HA (zone-redundant tier or geo-replication) on each data service.\"))\n cb.append(Check(\"R9\", \"Reliability\", \"PaaS using zone-redundant tiers?\",\n \"warning\", bool(get(spec, \"compute.zone_redundant\")),\n f\"compute.zone_redundant={get(spec, 'compute.zone_redundant')}\",\n \"Pick zone-redundant SKUs for PaaS services where available.\"))\n cb.append(Check(\"R10\", \"Reliability\", \"Chaos exercise in last 6 months?\",\n \"info\", bool(get(spec, \"operations.chaos_last_run\")),\n f\"operations.chaos_last_run={get(spec, 'operations.chaos_last_run')}\",\n \"Run a chaos gameday (see engineering/chaos-engineering skill) quarterly.\"))\n return cb\n\n\ndef check_security(spec: dict[str, Any]) -> list[Check]:\n cb = []\n cb.append(Check(\"S1\", \"Security\", \"Private endpoints for PaaS?\",\n \"critical\", bool(get(spec, \"network.private_endpoints\")),\n f\"private_endpoints={get(spec, 'network.private_endpoints')}\",\n \"Use Private Endpoint for all production PaaS access.\"))\n cb.append(Check(\"S2\", \"Security\", \"Secrets in Key Vault?\",\n \"critical\", bool(get(spec, \"security.key_vault\")),\n f\"security.key_vault={get(spec, 'security.key_vault')}\",\n \"Store all secrets in Key Vault; reference via @Microsoft.KeyVault(SecretUri=...) syntax.\"))\n cb.append(Check(\"S3\", \"Security\", \"Managed Identity for service-to-service auth?\",\n \"critical\", bool(get(spec, \"identity.managed_identity\")),\n f\"identity.managed_identity={get(spec, 'identity.managed_identity')}\",\n \"Use Managed Identity; avoid connection strings / shared keys.\"))\n cb.append(Check(\"S4\", \"Security\", \"MFA enforced for admin access?\",\n \"critical\", bool(get(spec, \"security.mfa_enforced\")),\n f\"security.mfa_enforced={get(spec, 'security.mfa_enforced')}\",\n \"Conditional Access policy: enforce MFA for all admin roles.\"))\n cb.append(Check(\"S5\", \"Security\", \"Defender for Cloud enabled?\",\n \"warning\", bool(get(spec, \"security.defender_for_cloud\")),\n f\"security.defender_for_cloud={get(spec, 'security.defender_for_cloud')}\",\n \"Enable Defender plans for services in use.\"))\n cb.append(Check(\"S6\", \"Security\", \"Diagnostic logs sent to Log Analytics?\",\n \"critical\", bool(get(spec, \"observability.log_analytics\")),\n f\"observability.log_analytics={get(spec, 'observability.log_analytics')}\",\n \"Enable diagnostic settings on every resource sending to Log Analytics.\"))\n cb.append(Check(\"S7\", \"Security\", \"RBAC at least-privileged scope?\",\n \"warning\", get(spec, \"identity.rbac_scope\", \"\") in (\"resource\", \"resource_group\"),\n f\"identity.rbac_scope={get(spec, 'identity.rbac_scope')}\",\n \"Scope RBAC to resource/resource-group, not subscription.\"))\n cb.append(Check(\"S8\", \"Security\", \"NSGs configured with least-privilege rules?\",\n \"warning\", bool(get(spec, \"network.nsg_least_privilege\")),\n f\"network.nsg_least_privilege={get(spec, 'network.nsg_least_privilege')}\",\n \"Audit NSGs for 0.0.0.0/0 inbound on management ports; restrict to known sources.\"))\n cb.append(Check(\"S9\", \"Security\", \"Encryption at rest enabled?\",\n \"critical\", bool(get(spec, \"security.encryption_at_rest\", True)),\n f\"security.encryption_at_rest={get(spec, 'security.encryption_at_rest', True)}\",\n \"Confirm encryption at rest (default for most PaaS; explicit for VMs).\"))\n cb.append(Check(\"S10\", \"Security\", \"TLS 1.2+ enforced?\",\n \"warning\", bool(get(spec, \"security.min_tls_1_2\", True)),\n f\"security.min_tls_1_2={get(spec, 'security.min_tls_1_2', True)}\",\n \"Set minimumTlsVersion: '1.2' on all services that expose it.\"))\n return cb\n\n\ndef check_cost(spec: dict[str, Any]) -> list[Check]:\n cb = []\n cb.append(Check(\"C1\", \"Cost\", \"Resources right-sized?\",\n \"warning\", bool(get(spec, \"cost.right_sized\")),\n f\"cost.right_sized={get(spec, 'cost.right_sized')}\",\n \"Audit by Azure Advisor; downsize SKUs running consistently under 25% utilization.\"))\n cb.append(Check(\"C2\", \"Cost\", \"Reserved Instances / Savings Plans for predictable workloads?\",\n \"warning\", bool(get(spec, \"cost.reservations_purchased\")),\n f\"cost.reservations_purchased={get(spec, 'cost.reservations_purchased')}\",\n \"Buy 1-yr or 3-yr commitments for steady baseline; up to 72% savings.\"))\n cb.append(Check(\"C3\", \"Cost\", \"Autoscaling enabled?\",\n \"warning\", bool(get(spec, \"compute.autoscale\")),\n f\"compute.autoscale={get(spec, 'compute.autoscale')}\",\n \"Same as R6; autoscale prevents over-provisioning.\"))\n cb.append(Check(\"C4\", \"Cost\", \"Spot / Low-Priority used for fault-tolerant workloads?\",\n \"info\", bool(get(spec, \"cost.spot_used\")),\n f\"cost.spot_used={get(spec, 'cost.spot_used')}\",\n \"Use spot for batch jobs, CI, dev fleets — up to 90% savings.\"))\n cb.append(Check(\"C5\", \"Cost\", \"Storage tiered (Hot/Cool/Cold/Archive) per access pattern?\",\n \"warning\", bool(get(spec, \"cost.storage_tiered\")),\n f\"cost.storage_tiered={get(spec, 'cost.storage_tiered')}\",\n \"Use lifecycle management to auto-tier blobs.\"))\n cb.append(Check(\"C6\", \"Cost\", \"Dev/test shut down outside business hours?\",\n \"info\", bool(get(spec, \"cost.devtest_schedule\")),\n f\"cost.devtest_schedule={get(spec, 'cost.devtest_schedule')}\",\n \"DevTest Labs or Automation runbook for 7pm-7am + weekend shutdown.\"))\n cb.append(Check(\"C7\", \"Cost\", \"Orphaned resources cleaned up (disks, IPs, snapshots)?\",\n \"warning\", bool(get(spec, \"cost.orphans_cleaned\")),\n f\"cost.orphans_cleaned={get(spec, 'cost.orphans_cleaned')}\",\n \"Periodically run Resource Graph queries for orphaned resources.\"))\n cb.append(Check(\"C8\", \"Cost\", \"Cosmos/SQL throughput right-sized?\",\n \"warning\", bool(get(spec, \"cost.db_throughput_right_sized\")),\n f\"cost.db_throughput_right_sized={get(spec, 'cost.db_throughput_right_sized')}\",\n \"Cosmos autoscale; SQL serverless for spiky; tune partition keys.\"))\n cb.append(Check(\"C9\", \"Cost\", \"Log Analytics retention tuned per table?\",\n \"warning\", bool(get(spec, \"cost.log_retention_tuned\")),\n f\"cost.log_retention_tuned={get(spec, 'cost.log_retention_tuned')}\",\n \"Tier retention per table (e.g., 30 days for app logs, 1yr for audit).\"))\n cb.append(Check(\"C10\", \"Cost\", \"Cost alerts/budgets configured?\",\n \"critical\", bool(get(spec, \"cost.budgets_configured\")),\n f\"cost.budgets_configured={get(spec, 'cost.budgets_configured')}\",\n \"Set monthly budgets per subscription/RG with alert thresholds.\"))\n return cb\n\n\ndef check_operations(spec: dict[str, Any]) -> list[Check]:\n cb = []\n cb.append(Check(\"O1\", \"Operations\", \"Infrastructure as code (Bicep/ARM/Terraform)?\",\n \"warning\", bool(get(spec, \"operations.iac\")),\n f\"operations.iac={get(spec, 'operations.iac')}\",\n \"Define all infra as code; review changes via PR.\"))\n cb.append(Check(\"O2\", \"Operations\", \"Deployments via CI/CD (no portal changes in prod)?\",\n \"critical\", bool(get(spec, \"operations.ci_cd\")),\n f\"operations.ci_cd={get(spec, 'operations.ci_cd')}\",\n \"Lock prod portal write access; deploy via pipelines only.\"))\n cb.append(Check(\"O3\", \"Operations\", \"Staging environment with prod-like config?\",\n \"warning\", bool(get(spec, \"operations.staging_env\")),\n f\"operations.staging_env={get(spec, 'operations.staging_env')}\",\n \"Stand up a staging environment for pre-prod validation.\"))\n cb.append(Check(\"O4\", \"Operations\", \"SLO-based alerting?\",\n \"warning\", bool(get(spec, \"observability.slo_alerts\")),\n f\"observability.slo_alerts={get(spec, 'observability.slo_alerts')}\",\n \"Define SLOs; alert on burn rate, not raw infra metrics.\"))\n cb.append(Check(\"O5\", \"Operations\", \"Runbooks documented?\",\n \"warning\", bool(get(spec, \"operations.runbooks\")),\n f\"operations.runbooks={get(spec, 'operations.runbooks')}\",\n \"Write runbooks for common operational tasks.\"))\n cb.append(Check(\"O6\", \"Operations\", \"Gradual rollout (canary/slots/blue-green)?\",\n \"warning\", bool(get(spec, \"operations.gradual_rollout\")),\n f\"operations.gradual_rollout={get(spec, 'operations.gradual_rollout')}\",\n \"Use deployment slots (App Service) or progressive delivery; see feature-flags-architect.\"))\n cb.append(Check(\"O7\", \"Operations\", \"On-call defined with escalation paths?\",\n \"warning\", bool(get(spec, \"operations.on_call_defined\")),\n f\"operations.on_call_defined={get(spec, 'operations.on_call_defined')}\",\n \"Set up on-call rotation with documented escalation.\"))\n cb.append(Check(\"O8\", \"Operations\", \"Blameless post-incident reviews?\",\n \"info\", bool(get(spec, \"operations.blameless_pir\")),\n f\"operations.blameless_pir={get(spec, 'operations.blameless_pir')}\",\n \"Conduct PIRs within 5 business days of every Sev1/2 incident.\"))\n cb.append(Check(\"O9\", \"Operations\", \"Azure Policy governance (tagging, allowed SKUs)?\",\n \"warning\", bool(get(spec, \"operations.azure_policy\")),\n f\"operations.azure_policy={get(spec, 'operations.azure_policy')}\",\n \"Use Azure Policy initiatives for governance + compliance.\"))\n cb.append(Check(\"O10\", \"Operations\", \"Deployment slots / zero-downtime swap?\",\n \"info\", bool(get(spec, \"operations.deployment_slots\")),\n f\"operations.deployment_slots={get(spec, 'operations.deployment_slots')}\",\n \"Use App Service deployment slots for safe deploys.\"))\n return cb\n\n\ndef check_performance(spec: dict[str, Any]) -> list[Check]:\n cb = []\n cb.append(Check(\"P1\", \"Performance\", \"Load tested under realistic load?\",\n \"warning\", bool(get(spec, \"performance.load_tested\")),\n f\"performance.load_tested={get(spec, 'performance.load_tested')}\",\n \"Use Azure Load Testing or k6/Locust; test at peak + 50% headroom.\"))\n cb.append(Check(\"P2\", \"Performance\", \"Caches (Redis/CDN/Front Door) in use?\",\n \"warning\", bool(get(spec, \"performance.caching\")),\n f\"performance.caching={get(spec, 'performance.caching')}\",\n \"Add Redis for app cache, Front Door/CDN for assets.\"))\n cb.append(Check(\"P3\", \"Performance\", \"Database queries optimized (indexes, query plans)?\",\n \"warning\", bool(get(spec, \"performance.db_optimized\")),\n f\"performance.db_optimized={get(spec, 'performance.db_optimized')}\",\n \"Review slow query logs; add indexes; check query plans.\"))\n cb.append(Check(\"P4\", \"Performance\", \"Data partitioned for scale-out?\",\n \"warning\", bool(get(spec, \"performance.data_partitioned\")),\n f\"performance.data_partitioned={get(spec, 'performance.data_partitioned')}\",\n \"Pick Cosmos partition key thoughtfully; SQL sharding if needed.\"))\n cb.append(Check(\"P5\", \"Performance\", \"Async patterns for I/O-bound work?\",\n \"info\", bool(get(spec, \"performance.async_io\")),\n f\"performance.async_io={get(spec, 'performance.async_io')}\",\n \"Use async/await; avoid thread starvation on I/O.\"))\n cb.append(Check(\"P6\", \"Performance\", \"Autoscaling responsive to load?\",\n \"warning\", bool(get(spec, \"compute.autoscale\")),\n f\"compute.autoscale={get(spec, 'compute.autoscale')}\",\n \"Tune autoscale rules; pre-scale for known peaks.\"))\n cb.append(Check(\"P7\", \"Performance\", \"Static assets served via CDN?\",\n \"warning\", bool(get(spec, \"performance.cdn_assets\")),\n f\"performance.cdn_assets={get(spec, 'performance.cdn_assets')}\",\n \"Use Front Door / Azure CDN for static assets.\"))\n cb.append(Check(\"P8\", \"Performance\", \"Workload profiled to find bottlenecks?\",\n \"info\", bool(get(spec, \"performance.profiled\")),\n f\"performance.profiled={get(spec, 'performance.profiled')}\",\n \"Use Application Insights Profiler; identify hot paths.\"))\n cb.append(Check(\"P9\", \"Performance\", \"Request/response sizes reasonable?\",\n \"info\", bool(get(spec, \"performance.payload_reviewed\")),\n f\"performance.payload_reviewed={get(spec, 'performance.payload_reviewed')}\",\n \"Audit for overfetching; use field-level GraphQL or projection queries.\"))\n cb.append(Check(\"P10\", \"Performance\", \"SLOs defined and tracked?\",\n \"warning\", bool(get(spec, \"performance.slos_defined\")),\n f\"performance.slos_defined={get(spec, 'performance.slos_defined')}\",\n \"Define SLI/SLO for latency p95/p99, error rate, throughput.\"))\n return cb\n\n\ndef score(checks: list[Check]) -> int:\n total_weight = sum(SEVERITY_WEIGHT[c.severity] for c in checks)\n if total_weight == 0:\n return 0\n passed_weight = sum(SEVERITY_WEIGHT[c.severity] for c in checks if c.pass_)\n return int(100 * passed_weight / total_weight)\n\n\ndef parse_args() -> argparse.Namespace:\n p = argparse.ArgumentParser(\n description=\"Score Azure workload against Well-Architected Framework\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=__doc__,\n )\n p.add_argument(\"--workload-config\", required=True, help=\"Path to workload YAML spec\")\n p.add_argument(\"--format\", choices=[\"markdown\", \"json\"], default=\"markdown\")\n p.add_argument(\"--output\", help=\"Output file path\")\n return p.parse_args()\n\n\ndef main() -> int:\n args = parse_args()\n try:\n spec = parse_yaml(Path(args.workload_config).read_text())\n except OSError as e:\n print(f\"error: {e}\", file=sys.stderr)\n return 2\n\n pillars = {\n \"Reliability\": check_reliability(spec),\n \"Security\": check_security(spec),\n \"Cost\": check_cost(spec),\n \"Operations\": check_operations(spec),\n \"Performance\": check_performance(spec),\n }\n scores = {name: score(checks) for name, checks in pillars.items()}\n overall = sum(scores.values()) // len(scores)\n failed = [c for checks in pillars.values() for c in checks if not c.pass_]\n failed.sort(key=lambda c: -SEVERITY_WEIGHT[c.severity])\n\n if args.format == \"json\":\n out = json.dumps(\n {\n \"workload_name\": spec.get(\"name\", \"unnamed\"),\n \"tier\": spec.get(\"tier\", 2),\n \"scores\": scores,\n \"overall_score\": overall,\n \"failed_checks\": [asdict(c) for c in failed],\n },\n indent=2,\n )\n else:\n lines = [\"# Azure WAF Assessment\", \"\"]\n lines.append(f\"**Workload:** {spec.get('name', 'unnamed')} \")\n lines.append(f\"**Tier:** {spec.get('tier', 2)}\")\n lines.append(\"\")\n lines.append(f\"## Overall Score: {overall}/100\")\n lines.append(\"\")\n lines.append(\"| Pillar | Score |\")\n lines.append(\"|--------|-------|\")\n for name, sc in scores.items():\n lines.append(f\"| {name} | {sc}/100 |\")\n lines.append(\"\")\n if failed:\n lines.append(f\"## Failed Checks ({len(failed)})\")\n lines.append(\"\")\n lines.append(\"| ID | Pillar | Severity | Question | Recommendation |\")\n lines.append(\"|----|--------|----------|----------|----------------|\")\n for c in failed:\n lines.append(f\"| {c.id} | {c.pillar} | {c.severity} | {c.question} | {c.recommendation[:80]} |\")\n out = \"\\n\".join(lines)\n\n if args.output:\n Path(args.output).write_text(out)\n print(f\"wrote {args.output}\", file=sys.stderr)\n else:\n print(out)\n return 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n","content_type":"text/x-python; charset=utf-8","language":"python","size":24059,"content_sha256":"107ad33741e65228e62288185df75a8b84bb092cf656715e4b7d753e3fc2940a"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Azure Cloud Architect","type":"text"}]},{"type":"paragraph","content":[{"text":"End-to-end Azure-specific architecture: service selection, Well-Architected Framework assessment, identity and networking patterns, cost optimization, and operational defaults. Provider-specific complement to our generic ","type":"text"},{"text":"senior-cloud-architect","type":"text","marks":[{"type":"code_inline"}]},{"text":" skill — that one covers cross-cloud patterns; this one knows AKS pricing tiers, when to pick Cosmos over SQL DB, and how Front Door differs from Application Gateway.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"When to use this skill","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Situation","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skill applies","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Designing an Azure architecture from scratch","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes — start with the ","type":"text"},{"text":"service selection decision tree","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reviewing an existing Azure architecture","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes — run ","type":"text"},{"text":"WAF assessment","type":"text","marks":[{"type":"strong"}]},{"text":" via ","type":"text"},{"text":"scripts/azure_waf_scorer.py","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Validating an ARM/Bicep/Terraform plan","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes — ","type":"text"},{"text":"scripts/azure_architecture_validator.py","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Estimating Azure cost for a workload","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes — ","type":"text"},{"text":"scripts/azure_cost_estimator.py","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Picking between AKS / App Service / Container Apps / Functions","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes — see ","type":"text"},{"text":"compute decision tree","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Setting up identity / RBAC / Managed Identity correctly","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes — see ","type":"text"},{"text":"identity reference","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Designing a multi-region active-active or DR posture","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes — see ","type":"text"},{"text":"reliability reference","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Picking SQL DB vs Cosmos vs Postgres Flexible vs Storage","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yes — see ","type":"text"},{"text":"data store decision tree","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Going to production without WAF review","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Don't — run the WAF scorer first","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Compute decision tree","type":"text"}]},{"type":"paragraph","content":[{"text":"Azure offers many compute options; picking the wrong one wastes money and adds operational burden.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Stateless HTTP service?\n├── Need full control over OS / sidecar / custom runtime?\n│ └── → AKS (Kubernetes; serious operational investment)\n├── Standard web app (Node / Python / .NET / Java)?\n│ ├── \u003c 5 services, low traffic, want zero infra?\n│ │ └── → App Service (Linux/Windows; managed PaaS)\n│ ├── Need autoscale to zero + container runtime?\n│ │ └── → Container Apps (KEDA-based; sweet spot for microservices)\n│ └── Need true serverless / event-driven?\n│ └── → Functions (Premium for VNet/always-warm; Consumption for cheap+bursty)\n├── Batch / job processing?\n│ └── → Container Apps Jobs OR Batch (HPC-scale)\n└── Long-running stateful processes / legacy?\n └── → VMs / VMSS\n\nStateful service (DBs you self-manage)?\n├── → Generally prefer managed: SQL DB, Cosmos, PG Flexible\n├── Or VM + your own DB (rarely the right call)\n\nML inference?\n├── Realtime, GPU?\n│ └── → AKS (GPU node pools) OR Azure ML managed endpoints\n└── Batch?\n └── → Azure ML pipelines OR Container Apps Jobs\n\nStatic frontend?\n└── → Static Web Apps (auto SSL, GitHub/Bitbucket deploy)\n\nAPI gateway?\n├── In-VNet, internal-only?\n│ └── → Application Gateway\n├── Global edge, custom routing, WAF?\n│ └── → Front Door\n├── API management (rate limit, dev portal, monetization)?\n│ └── → API Management","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/azure-services-reference.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/azure-services-reference.md","title":null}}]},{"text":" for service-by-service depth: pricing tiers, SLAs, limits, when to upgrade.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Data store decision tree","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Relational?\n├── Standard OLTP, low-to-medium scale?\n│ └── → Azure SQL Database (Single DB; serverless tier for spiky)\n├── Want PostgreSQL specifically?\n│ └── → Azure Database for PostgreSQL Flexible Server\n├── Want MySQL specifically?\n│ └── → Azure Database for MySQL Flexible Server\n├── Multi-region with high concurrency, global reads?\n│ └── → Cosmos DB (PostgreSQL or NoSQL API)\n\nDocument / NoSQL?\n├── Global distribution, multiple consistency models, multi-region writes?\n│ └── → Cosmos DB\n├── Single-region key-value at scale?\n│ └── → Azure Table Storage (cheap) OR Cosmos DB (Table API)\n\nKey-value cache?\n└── → Azure Cache for Redis (Standard for HA, Premium for VNet/persistence)\n\nBlob / object storage?\n└── → Storage Account (Blob); pick Hot / Cool / Cold / Archive tier per access pattern\n\nTime-series / metrics?\n├── Operational (low cost, queryable)?\n│ └── → Azure Monitor Logs (Log Analytics workspace)\n├── Application time series?\n│ └── → Azure Data Explorer (Kusto) — purpose-built\n\nSearch?\n└── → Azure AI Search (formerly Cognitive Search) — managed Lucene-based\n\nVector / embeddings?\n├── Same workload as existing Cosmos / SQL DB?\n│ └── → Cosmos DB (vector search support) OR Azure SQL DB (vector type)\n└── Dedicated vector search?\n └── → Azure AI Search (vector indexes)\n\nData warehouse?\n├── \u003c 10TB, occasional queries?\n│ └── → Azure SQL Database (DTU/vCore high tier) OR Synapse Serverless\n└── > 10TB, analytical workloads?\n └── → Azure Synapse Analytics (Dedicated Pool) OR Microsoft Fabric","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Networking patterns","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Three core building blocks","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Component","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What it does","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"When","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Virtual Network (VNet)","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"L3 isolation; private IP space; subnets","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Every non-trivial Azure deployment","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Private Endpoint","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Brings Azure PaaS services into your VNet via private IP","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default for production access to PaaS (Storage, SQL, etc.)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Service Endpoint","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Lower-cost predecessor to Private Endpoint; restricts access to your VNet","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cost-sensitive, lower-security workloads only","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Gateway services","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Service","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use when","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Application Gateway (v2)","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"L7 LB inside VNet; WAF; OWASP rules; private + public modes; not global","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Front Door","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Global L7; multi-region routing; WAF at edge; CDN; URL-based routing","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Firewall","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"L3-L4-L7 stateful; egress filtering with FQDN allowlists","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"NAT Gateway","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Predictable outbound IP for VNet egress; replaces SNAT exhaustion concerns","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"VPN Gateway / ExpressRoute","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"On-prem connectivity (S2S VPN cheaper; ER private + faster)","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Common networking patterns","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pattern","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"When","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Hub-and-spoke","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Central hub VNet with shared services (firewall, ER, AD DS), peered with workload-specific spoke VNets","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Multi-team / multi-workload orgs","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"VWAN","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Microsoft-managed hub network simplifying multi-region + on-prem","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"When hub-spoke complexity gets painful","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Private Link for everything","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Every PaaS access via Private Endpoint; no public endpoints","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default for production / regulated workloads","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Azure Front Door + AppGw","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Global edge (AFD) → regional WAF/L7 (AGW) → backend","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"High-traffic global apps","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Identity patterns","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Entra ID, Managed Identity, RBAC","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Concept","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Microsoft Entra ID","type":"text","marks":[{"type":"strong"}]},{"text":" (formerly Azure AD)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Identity provider for users, groups, apps","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Service Principal","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Identity for an app; has a secret or cert","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Managed Identity","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Service Principal whose lifecycle is tied to an Azure resource; no secrets","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"System-assigned Managed Identity","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"One per resource; deleted when resource is deleted","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"User-assigned Managed Identity","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Independent lifecycle; can attach to multiple resources","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Workload Identity (AKS)","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Federated identity for K8s pods; no secret mounting","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Choosing identity","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Service running in Azure that calls other Azure services?\n├── Single Azure resource → System-assigned MI\n├── Multiple resources sharing identity (e.g., a pool of VMSS instances) → User-assigned MI\n├── K8s pod → AKS Workload Identity\n└── External app (CI/CD, on-prem) → Service Principal with cert (NOT secret)\n\nService calling external API (non-Azure)?\n└── Service Principal OR app secret in Key Vault, accessed via MI\n\nUser-facing auth?\n└── Entra ID with OIDC; B2C if customer-facing identity","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"RBAC scopes (least privilege)","type":"text"}]},{"type":"paragraph","content":[{"text":"Assign RBAC at the smallest necessary scope:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Scope","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"When","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resource","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Most specific; preferred default","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resource group","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"When the role applies to a logical group","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Subscription","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Only for subscription-wide admins","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Management group","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cross-subscription enterprise governance","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Use built-in roles when they exist (Reader, Contributor, Storage Blob Data Reader, etc.). Custom roles only when truly needed.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Azure Well-Architected Framework (WAF)","type":"text"}]},{"type":"paragraph","content":[{"text":"Microsoft's WAF has five pillars. Every architecture should be assessed against all five.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pillar","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Core question","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reliability","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Will it stay up under expected and unexpected load?","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Security","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Can it defend against threats, contain breaches, recover from compromise?","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cost Optimization","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Is it spending only what's needed for the value delivered?","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Operational Excellence","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Can the team deploy, observe, and recover changes safely?","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Performance Efficiency","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Does it meet performance needs without over-provisioning?","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"scripts/azure_waf_scorer.py --workload-config workload.yaml","type":"text","marks":[{"type":"code_inline"}]},{"text":" to score a workload against each pillar with concrete questions and recommendations.","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/azure-well-architected.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/azure-well-architected.md","title":null}}]},{"text":" for the per-pillar deep dive: 10-question checklist per pillar, common findings, remediation patterns.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Cost optimization","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Cost levers from biggest to smallest","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Lever","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Typical savings","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Effort","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Right-sizing","type":"text","marks":[{"type":"strong"}]},{"text":" (matching SKU to load)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"30-50%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Low","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reserved Instances / Savings Plans","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"20-72%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Low (commitment)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Autoscaling","type":"text","marks":[{"type":"strong"}]},{"text":" (compute + DB)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"20-40%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Medium","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Spot Instances","type":"text","marks":[{"type":"strong"}]},{"text":" (for batch / tolerant workloads)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"up to 90%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Medium","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Storage tiering","type":"text","marks":[{"type":"strong"}]},{"text":" (Hot/Cool/Cold/Archive)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"30-70% on storage","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Low","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Egress reduction","type":"text","marks":[{"type":"strong"}]},{"text":" (Front Door caching; CDN; private peering)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Variable, can be huge","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Medium-High","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Decommission unused","type":"text","marks":[{"type":"strong"}]},{"text":" (orphan disks, idle resources)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Variable","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Low","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Region choice","type":"text","marks":[{"type":"strong"}]},{"text":" (cheaper regions for non-latency-sensitive)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"10-25%","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"High (move)","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Cost anti-patterns","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Premium tier by default.","type":"text","marks":[{"type":"strong"}]},{"text":" Premium App Service / Cosmos throughput / SQL DTUs that the workload doesn't need.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No autoscaling.","type":"text","marks":[{"type":"strong"}]},{"text":" Always provisioned at peak. Easy 30-40% savings if added.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Egress through public internet.","type":"text","marks":[{"type":"strong"}]},{"text":" Cross-region traffic via public endpoints is expensive; use VNet peering or Private Link.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Unused Log Analytics retention.","type":"text","marks":[{"type":"strong"}]},{"text":" Keeping 730 days of debug logs at default rate.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cosmos DB autoscale ceiling too high.","type":"text","marks":[{"type":"strong"}]},{"text":" Pays for unused capacity.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Premium-tier Managed Disks for non-critical workloads.","type":"text","marks":[{"type":"strong"}]},{"text":" Standard SSD is usually enough.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"references/azure-cost-optimization.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/azure-cost-optimization.md","title":null}}]},{"text":" for the full lever catalog and detection patterns.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"End-to-end workflows","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Workflow: Design a new workload","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Understand requirements","type":"text","marks":[{"type":"strong"}]},{"text":" — traffic, data scale, latency, region requirements, compliance.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pick compute","type":"text","marks":[{"type":"strong"}]},{"text":" using the decision tree.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pick data stores","type":"text","marks":[{"type":"strong"}]},{"text":" using the decision tree.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Design networking","type":"text","marks":[{"type":"strong"}]},{"text":" — VNet topology, Private Endpoints, gateway pattern.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Design identity","type":"text","marks":[{"type":"strong"}]},{"text":" — Managed Identities, RBAC scopes.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Plan observability","type":"text","marks":[{"type":"strong"}]},{"text":" — Log Analytics workspace, Application Insights, metrics.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Estimate cost","type":"text","marks":[{"type":"strong"}]},{"text":" with ","type":"text"},{"text":"scripts/azure_cost_estimator.py","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validate against WAF","type":"text","marks":[{"type":"strong"}]},{"text":" with ","type":"text"},{"text":"scripts/azure_waf_scorer.py","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Document","type":"text","marks":[{"type":"strong"}]},{"text":" the architecture; share for review.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Workflow: Review an existing Azure architecture","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Gather artifacts","type":"text","marks":[{"type":"strong"}]},{"text":" — ARM/Bicep/Terraform code, network diagrams, service inventory.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run the validator","type":"text","marks":[{"type":"strong"}]},{"text":" — ","type":"text"},{"text":"scripts/azure_architecture_validator.py --bicep ./infra/*.bicep","type":"text","marks":[{"type":"code_inline"}]},{"text":" flags structural issues.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run WAF scorer","type":"text","marks":[{"type":"strong"}]},{"text":" with the workload's actual config.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Identify high-cost components","type":"text","marks":[{"type":"strong"}]},{"text":" with the cost estimator.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Produce findings","type":"text","marks":[{"type":"strong"}]},{"text":" by pillar with severity and recommendation.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Workflow: Migrate from AWS / GCP to Azure","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Map services","type":"text","marks":[{"type":"strong"}]},{"text":" — most have equivalents but not 1:1 (e.g., SQS → Service Bus or Storage Queue depending on use; SNS → Event Grid; Lambda → Functions; DynamoDB → Cosmos DB).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Re-evaluate the architecture","type":"text","marks":[{"type":"strong"}]},{"text":" in Azure-native terms before lift-and-shift; some patterns work better here, others worse.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Network parity","type":"text","marks":[{"type":"strong"}]},{"text":" — VPC equivalent (VNet); IAM equivalent (Entra + RBAC); private connectivity (Private Endpoint).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Data migration","type":"text","marks":[{"type":"strong"}]},{"text":" — Azure Database Migration Service for many SQL/PG scenarios; Storage Migration Service for files.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cost re-estimate","type":"text","marks":[{"type":"strong"}]},{"text":" — Azure pricing differs from AWS / GCP per-service; don't assume parity.","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Anti-patterns (Azure-specific)","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Storing secrets in App Settings / env vars instead of Key Vault.","type":"text","marks":[{"type":"strong"}]},{"text":" Use Key Vault references in App Settings.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Single-region production","type":"text","marks":[{"type":"strong"}]},{"text":" for a tier-1 workload. Use paired regions + Traffic Manager / Front Door.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No Resource Locks on critical resources.","type":"text","marks":[{"type":"strong"}]},{"text":" A single ","type":"text"},{"text":"az group delete","type":"text","marks":[{"type":"code_inline"}]},{"text":" away from disaster.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Public storage account access enabled","type":"text","marks":[{"type":"strong"}]},{"text":" (\"AllowBlobPublicAccess\"). Disable at storage-account level unless explicitly needed.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Premium SKU for everything.","type":"text","marks":[{"type":"strong"}]},{"text":" Premium SQL / Premium App Service / Premium Cosmos used by default without need.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Shared keys / connection strings","type":"text","marks":[{"type":"strong"}]},{"text":" for service-to-service auth instead of Managed Identity.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No diagnostic settings","type":"text","marks":[{"type":"strong"}]},{"text":" sending logs to Log Analytics → no audit trail.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Hub-and-spoke without UDRs to force egress through firewall.","type":"text","marks":[{"type":"strong"}]},{"text":" Defeats the firewall's purpose.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"AKS without managed identities, RBAC, or network policies","type":"text","marks":[{"type":"strong"}]},{"text":" — provisioning Kubernetes the easy way leaves obvious gaps.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Functions on Consumption plan for VNet integration.","type":"text","marks":[{"type":"strong"}]},{"text":" Consumption can't do VNet; need Premium or Dedicated.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Mixing Cosmos consistency levels","type":"text","marks":[{"type":"strong"}]},{"text":" without understanding the trade-off; Session is the right default for most.","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Tooling outputs","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Script","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Input","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Output","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/azure_architecture_validator.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bicep/ARM file or YAML workload spec","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Structural issues, anti-pattern findings, missing best-practice settings","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/azure_cost_estimator.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"YAML workload spec (services + tiers + scale)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Per-service monthly cost estimate, total, optimization opportunities","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/azure_waf_scorer.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"YAML workload spec","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Score per WAF pillar, gap analysis, recommendations","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"All scripts: stdlib only, argparse CLI, JSON or markdown output.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"azure-services-reference.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/azure-services-reference.md","title":null}}]},{"text":" — per-service depth: tiers, SLAs, limits, when to upgrade","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"azure-well-architected.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/azure-well-architected.md","title":null}}]},{"text":" — 5-pillar WAF assessment with questions and remediations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"azure-cost-optimization.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/azure-cost-optimization.md","title":null}}]},{"text":" — cost levers, anti-patterns, detection heuristics","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Related skills","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"engineering/senior-cloud-architect","type":"text","marks":[{"type":"code_inline"}]},{"text":" — generic multi-cloud architecture patterns","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"engineering/aws-solution-architect","type":"text","marks":[{"type":"code_inline"}]},{"text":" — AWS counterpart","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"engineering/gcp-cloud-architect","type":"text","marks":[{"type":"code_inline"}]},{"text":" — GCP counterpart","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"engineering/kubernetes-operator","type":"text","marks":[{"type":"code_inline"}]},{"text":" — for AKS operator-pattern workloads","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ra-qm-team/information-security-manager-iso27001","type":"text","marks":[{"type":"code_inline"}]},{"text":" — for compliance-mapped controls (Azure has built-in Defender / Compliance Manager)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ra-qm-team/soc2-compliance-expert","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Azure-specific SOC 2 evidence collection","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"azure-cloud-architect","author":"@skillopedia","source":{"stars":209,"repo_name":"claude-skills","origin_url":"https://github.com/borghei/claude-skills/blob/HEAD/engineering/azure-cloud-architect/SKILL.md","repo_owner":"borghei","body_sha256":"698daa8b155e55d82a3e3ef8b30f69004d3e6592b80a605b5956d01d13726362","cluster_key":"42b4dd008f14d6a1317ee3f1c8e1609e39d7ab6934cc0f146cefc1a5d6881958","clean_bundle":{"format":"clean-skill-bundle-v1","source":"borghei/claude-skills/engineering/azure-cloud-architect/SKILL.md","attachments":[{"id":"00fc4a63-4de9-5251-811a-d58169194f7e","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/00fc4a63-4de9-5251-811a-d58169194f7e/attachment.md","path":"references/azure-cost-optimization.md","size":12879,"sha256":"8ac8f6574a59e8d1d4cce41af17b598cacb85e41fbba1278b65170cae9b8bbe7","contentType":"text/markdown; charset=utf-8"},{"id":"478359df-00eb-5ab7-8390-836bf9845599","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/478359df-00eb-5ab7-8390-836bf9845599/attachment.md","path":"references/azure-services-reference.md","size":17196,"sha256":"3d351c1b9845f2642eb0bf4bb5f45544c64a06b3a02a7d492bc06b0bbf0dae10","contentType":"text/markdown; charset=utf-8"},{"id":"79f60e26-ee7b-575c-9f51-df290eab9fda","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/79f60e26-ee7b-575c-9f51-df290eab9fda/attachment.md","path":"references/azure-well-architected.md","size":18192,"sha256":"f1072249c190ae7cdbd116ad3a5d97c55aa9a6bcbcaccb4be5690fb8bc88fc54","contentType":"text/markdown; charset=utf-8"},{"id":"327cd5cf-e771-575b-8b7f-ed78b30b954d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/327cd5cf-e771-575b-8b7f-ed78b30b954d/attachment.py","path":"scripts/azure_architecture_validator.py","size":14794,"sha256":"090e4ccd1d21503ee0c28624ec8bb495f90f1b8acdc470fa29363eba16165514","contentType":"text/x-python; charset=utf-8"},{"id":"62efa3db-35d6-53f4-8a93-229917219e47","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/62efa3db-35d6-53f4-8a93-229917219e47/attachment.py","path":"scripts/azure_cost_estimator.py","size":16568,"sha256":"d5e71018dfcd5832fd4936924d996e1d331ef7bb3f9153ac6df19b13a1b065ab","contentType":"text/x-python; charset=utf-8"},{"id":"175d8139-fd00-5c31-9099-e4748442017c","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/175d8139-fd00-5c31-9099-e4748442017c/attachment.py","path":"scripts/azure_waf_scorer.py","size":24059,"sha256":"107ad33741e65228e62288185df75a8b84bb092cf656715e4b7d753e3fc2940a","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"6105f8ee9ea3349e51cf7b59f500b2be7fc8bfe5ec4f3ffd5bf645029c22e2e7","attachment_count":6,"text_attachments":6,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"engineering/azure-cloud-architect/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"security","category_label":"Security"},"exact_dupes_collapsed_into_this":0},"license":"MIT + Commons Clause","version":"v1","category":"security","metadata":{"tags":["azure","cloud-architecture","well-architected-framework","aks","app-service","entra-id","networking","cost-optimization"],"author":"borghei","domain":"engineering","updated":"2026-05-27T00:00:00.000Z","version":"1.0.0","category":"engineering"},"import_tag":"clean-skills-v1","description":"Design, review, and validate Azure cloud architectures. Use when picking the right Azure compute (AKS / App Service / Container Apps / Functions / VMs / VMSS), data store (SQL DB / Cosmos / Postgres Flexible / Storage), networking (VNet / Private Endpoint / Front Door / Application Gateway), identity (Entra ID / Managed Identity / RBAC scopes), or applying the Azure Well-Architected Framework (Reliability, Security, Cost Optimization, Operational Excellence, Performance Efficiency) to a workload. Pairs with our existing senior-cloud-architect (multi-cloud, abstract patterns) by going deep on Azure-specific services, pricing, and operational defaults.\n"}},"renderedAt":1782987562834}

Azure Cloud Architect End-to-end Azure-specific architecture: service selection, Well-Architected Framework assessment, identity and networking patterns, cost optimization, and operational defaults. Provider-specific complement to our generic skill — that one covers cross-cloud patterns; this one knows AKS pricing tiers, when to pick Cosmos over SQL DB, and how Front Door differs from Application Gateway. --- When to use this skill | Situation | Skill applies | |-----------|---------------| | Designing an Azure architecture from scratch | Yes — start with the service selection decision tree |…