{"id":51097260,"url":"https://github.com/dvmrry/zscaler-as-code","last_synced_at":"2026-06-24T07:32:42.937Z","repository":{"id":363856578,"uuid":"1265137672","full_name":"dvmrry/zscaler-as-code","owner":"dvmrry","description":"Continuous Terraform reconciliation for Zscaler (ZIA/ZPA/ZCC): schema-generated modules, typed JSON config, brownfield import adoption, drift-to-PR backfills with audit attribution. A living pipeline, not a one-shot exporter.","archived":false,"fork":false,"pushed_at":"2026-06-18T02:49:59.000Z","size":1242,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T04:24:41.297Z","etag":null,"topics":["drift-detection","gitops","infrastructure-as-code","terraform","zia","zpa","zscaler"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dvmrry.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-10T13:53:42.000Z","updated_at":"2026-06-18T02:50:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dvmrry/zscaler-as-code","commit_stats":null,"previous_names":["dvmrry/zscaler-as-code"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dvmrry/zscaler-as-code","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmrry%2Fzscaler-as-code","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmrry%2Fzscaler-as-code/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmrry%2Fzscaler-as-code/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmrry%2Fzscaler-as-code/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dvmrry","download_url":"https://codeload.github.com/dvmrry/zscaler-as-code/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvmrry%2Fzscaler-as-code/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34722702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-24T02:00:07.484Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drift-detection","gitops","infrastructure-as-code","terraform","zia","zpa","zscaler"],"created_at":"2026-06-24T07:32:42.010Z","updated_at":"2026-06-24T07:32:42.908Z","avatar_url":"https://github.com/dvmrry.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zscaler-as-code\n\nContinuous Terraform reconciliation for Zscaler (ZIA + ZPA + ZCC):\nmodule code is generated from the provider schemas, all configuration\nlives in typed JSON (`.auto.tfvars.json`), existing tenants are adopted\nvia import blocks, and scheduled drift detection opens backfill PRs with\nitem-level diffs and audit-trail attribution.\n\n**How this differs from [zscaler-terraformer](https://github.com/zscaler/zscaler-terraformer):**\nthe official tool is a one-shot exporter — it snapshots a tenant into\nstatic hand-maintained HCL. This is a living pipeline: config stays\ntyped data, modules regenerate from schema dumps, and the tenant and\nthe repo are continuously reconciled through gated PRs.\n\nThis is a template: it ships with fictional sample data and contains no\ncredentials or tenant-specific values. Bring your own tfvars in a private\nrepo. See `AGENTS.md` for the repo invariants.\n\n## Design constraints\n\n- The provider schema is the single source of truth: modules and JSON\n  Schemas are generated, committed, and checked for drift in CI.\n- Generated output is deterministic — provider bumps produce reviewable\n  git diffs.\n- Python tooling is stdlib-only at a Python 3.6 syntax floor so it runs\n  in restricted enterprise environments.\n- All logic lives in `make` targets; CI pipelines are thin shells.\n\n## Entry points\n\nAll workflows are `make` targets — run `make help` to list them (stays\nauthoritative). Do not invent other invocation paths. For step-by-step\nadoption and drift-detection procedures, see `RUNBOOK.md`.\n\nCommon ops targets:\n\n| Target | Purpose |\n|---|---|\n| `make gen-env TENANT=\u003clabel\u003e` | Generate Terraform root modules for a tenant |\n| `make plan TENANT=\u003clabel\u003e` | Terraform plan all roots for a tenant (real creds via env) |\n| `make drift TENANT=\u003clabel\u003e` | Fetch live config, transform, and report drift vs committed state (exits 3 on drift) |\n| `make check-envs` | Regenerate all tenant env roots and fail if any differ from committed |\n| `make test-envs TENANT=\u003clabel\u003e` | Mock-provider smoke tests across a tenant's env roots |\n| `make validate-imports TENANT=\u003clabel\u003e` | Validate fixture import addresses against a tenant's roots |\n| `make validate-config` | Validate config/ tfvars against generated JSON Schemas (dev-only; tries uv if jsonschema is not installed, skips gracefully if neither is available) |\n\n`tools/registry.json` is the generated provider-surface catalog. Every\npublished ZIA/ZPA/ZCC Terraform resource has a generated module and tfvars\nschema; only entries with a `fetch` block are live-read by `make fetch`.\n`make headroom-report RESOURCE='zia zpa zcc'` shows the split between\nfetch-managed resources, derived resources, generated-but-not-fetch-wired\nresources, and known non-bulk/adoption holds.\n\n## Layout\n\n    RUNBOOK.md                 adoption and drift-detection procedures\n    modules/\u003cresource-type\u003e/   GENERATED Terraform modules — never hand-edit\n    schemas/provider/          pinned provider schema dumps (make schemas)\n    schemas/tfvars/            generated JSON Schemas for config files\n    tools/                     stdlib-only Python (3.6-floor) + overrides\n    envs/\u003ctenant\u003e/             root modules, split state\n    config/\u003ctenant\u003e/           fictional sample tfvars\n    lookups/\u003ctenant\u003e/          generated readable-name lookup sidecars\n    imports/\u003ctenant\u003e/          transform-emitted import blocks\n\nDirectories not yet present are created by later build phases.\n\n## CI\n\nSee `pipelines/README.md` for Azure DevOps, GitHub Actions, and Bitbucket\nexamples — all thin shells over `make`. Point a pipeline definition at the\nrelevant example (or copy it) and adapt the agent pool and toolchain setup\nto your environment.\n\n## Regenerating provider schemas\n\n`make schemas` runs `terraform providers schema -json` against the pinned\nproviders in `tools/schema-extract/` and rewrites `schemas/provider/`.\nTo bump a provider: edit the `version` pin in `tools/schema-extract/main.tf`,\nrun `terraform -chdir=tools/schema-extract init -upgrade`, then\n`make schemas` and review the resulting git diff.\n\nSchema extraction is an authoring step. Everywhere else — consuming\nenvironments and CI included — the committed dumps are read-only inputs:\ndo not regenerate or hand-edit `schemas/provider/` there. `make schemas\nCHECK=1` is the authoring-side pre-commit guard for pin bumps; extraction\noutput can legitimately vary with the local terraform and provider\nversions, which is exactly why it happens in one place.\n\n## Deploying privately while consuming template updates\n\nRun a private deployment repo as a downstream of this template (clone +\nprivate remote; `git pull \u003ctemplate-remote\u003e main` to update). Merges stay\ntrivial as long as the PATH CONTRACT holds:\n\n- **Template-owned (never edit downstream):** `Makefile`, `tools/`,\n  `modules/`, `schemas/`, `envs/demo/`, `config/demo/`, `pipelines/*.example.yml`,\n  the docs. A local edit here is a future merge conflict and a fork —\n  change the template via PR instead, or extend via the seams below.\n- **Deployment-owned (never shipped by the template):** `config/\u003cyour-tenants\u003e/`,\n  `imports/\u003cyour-tenants\u003e/`, `envs/\u003cyour-tenants\u003e/`, `pulls/` (gitignored),\n  `backend.conf`, your operative pipeline yamls (repo root or your own\n  directory), and:\n  - **`local.mk`** — custom make targets and variable overrides; the\n    template Makefile `-include`s it and never ships it.\n  - **`company/` (or any directory the template doesn't use)** — your\n    scripts, docs, runbooks.\n- **Derived-by-ritual:** operative pipeline yamls are adapted FROM the\n  examples and do not update automatically — after pulling template\n  updates, diff them against `pipelines/*.example.yml` (see\n  pipelines/README.md).\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvmrry%2Fzscaler-as-code","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdvmrry%2Fzscaler-as-code","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvmrry%2Fzscaler-as-code/lists"}