Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Multi-Cloud Governance and Policy as Code

By Kokil Thapa | Last reviewed: August 2026

Your team provisions workloads on AWS for production, Azure for analytics, and maybe GCP for ML experiments—and within weeks you have public S3 buckets, untagged resources, and IAM roles that violate your own standards. Multi-Cloud Governance and Policy as Code is how you stop that drift before it reaches a bill or an audit. Instead of PDF runbooks and quarterly checklist reviews, you encode rules as versioned policy files, run them in CI against Terraform and Kubernetes manifests, and block non-compliant changes automatically. If you are already thinking about multi-cloud architecture patterns, governance is the layer that keeps that architecture safe as headcount and cloud accounts grow.

What is Multi-Cloud Governance and Policy as Code?

Multi-cloud governance is the set of processes, roles, and guardrails that keep resources consistent, auditable, and within budget when you operate across more than one public cloud. Policy as Code (PaC) is the mechanism: policies are written in a declarative language, stored in Git, reviewed in pull requests, and evaluated by automated engines—not left to memory or Slack reminders.

In practice, governance spans four domains that overlap on every cloud:

  • Security: encryption at rest, no public endpoints, least-privilege IAM, approved regions.
  • Cost: mandatory cost-centre tags, instance-size caps, idle-resource rules.
  • Compliance: CIS benchmarks, SOC 2 controls, data-residency constraints.
  • Operations: naming conventions, backup retention, approved AMIs or machine images.

Native cloud policy engines—AWS Organizations SCPs, Azure Policy, GCP Organization Policies—enforce rules inside each provider. Policy as Code tools sit one layer above: they validate the intent in your Terraform, Pulumi, or Kubernetes YAML before anything is applied, giving you one pipeline for three clouds instead of three separate manual review processes.

Multi-Cloud Governance StackGit: Policies + IaCCI: OPA / Checkov / SentinelPlan + Policy GateTerraform / OpenTofu ApplyAWSSCPs + ConfigAzureAzure PolicyGCPOrg Policies
Multi-Cloud Governance and Policy as Code: versioned policies in Git, automated CI gates, then native enforcement per cloud provider.

How policy as code differs from documentation

A written standard says "all S3 buckets must block public access." Policy as code encodes that rule so a pull request adding acl = "public-read" fails the build. The policy file, the Terraform module, and the CI log become audit evidence. That shift matters when a Nepali fintech startup chases SOC 2 or when a SaaS product stores PII subject to Nepal's data-privacy expectations—you need repeatable proof, not screenshots of console settings.

Why do teams need policy as code in multi-cloud environments?

Single-cloud teams can sometimes rely on console guardrails and one platform team's tribal knowledge. Multi-cloud breaks that model fast. Each provider names resources differently, exposes different defaults, and bills in different currencies. A developer who learned AWS tagging conventions will mis-tag Azure resource groups on day one unless automation catches it.

The pain points I see repeatedly on client projects and in production deployments:

  1. Configuration drift: Emergency hotfixes bypass standards; six months later nobody remembers which bucket is exposed.
  2. Inconsistent tagging: FinOps reports are useless when cost-centre exists on AWS but CostCenter on Azure.
  3. Shadow IT: A second AWS account or Azure subscription spun up for a demo never gets decommissioned.
  4. Audit scramble: Compliance asks for encryption proof across 200 resources; you grep CloudTrail instead of pointing at Git history.

Policy as code addresses each item at the point of change. Combined with centralised Terraform state for multi-cloud, you get a single approval path for infrastructure intent regardless of target cloud.

Governance that lives only in Confluence is governance that fails the first busy release week.

Which policy-as-code tools work best across AWS, Azure, and GCP?

No single tool covers every layer. Mature teams stack complementary engines: a universal IaC scanner, an optional admission controller for Kubernetes, and native org-level policies as the last line of defence.

ToolBest forCloud coverageLanguage / formatTypical gate
CheckovTerraform, CloudFormation, K8s YAML scanningAWS, Azure, GCP (+100 frameworks)Python policies + YAMLCI on terraform plan JSON
OPA + ConftestCustom cross-cloud rulesAny JSON/YAML inputRegoCI + admission webhook
HashiCorp SentinelTerraform Cloud/Enterprise policy setsAll Terraform providersSentinel DSLRemote plan/apply in TFC
tfsec / TrivyFast Terraform security scansMajor providersGo rulesetsCI pre-merge
Azure Policy / AWS SCPsRuntime enforcement at org levelSingle cloud eachJSON / HCLAPI deny on non-compliance

For teams already standardising on Terraform or OpenTofu, Checkov plus OPA covers most cross-cloud needs without vendor lock-in to a single cloud's policy language. Sentinel shines when you pay for Terraform Cloud and want policy sets attached to workspaces—see the dedicated walkthrough on Sentinel policy as code for Terraform for that path.

Policy Tool SelectionNeed cross-cloud IaC scan?YesCheckov + tfsecNoSingle cloud only?Native org policiesCustom business rules?OPA RegoTFC user?Sentinel
Choosing policy-as-code tooling: start with IaC scanners, add OPA for bespoke rules, layer native org policies for runtime denial.

How do you implement Multi-Cloud Governance and Policy as Code step by step?

Start narrow. Pick five rules that already caused incidents or invoice surprises—not fifty controls copied from a CIS PDF. Ship those in CI, measure false-positive rate for two sprints, then expand.

Step 1: Define a cross-cloud policy baseline

Write a short internal standard covering mandatory tags, allowed regions, encryption defaults, and forbidden resource patterns. Map each rule to a cloud-agnostic identifier:

# policies/baseline.yaml — team convention (documentation)
rules:
  - id: TAG-001
    description: Every billable resource must have cost_centre, environment, owner
  - id: SEC-001
    description: Block public object storage and open security groups on 0.0.0.0/0:22
  - id: REG-001
    description: Production only in ap-south-1, eastus, asia-south1

Align tag keys across clouds before you automate. Use lowercase snake_case everywhere—cost_centre, not three variants—so multi-cloud cost reporting actually joins in your FinOps dashboard.

Step 2: Add Checkov to CI against Terraform plan output

Generate a plan JSON file and scan it. This catches issues in modules before apply:

terraform init -backend=false
terraform plan -out=tfplan.binary
terraform show -json tfplan.binary > tfplan.json

pip install checkov
checkov -f tfplan.json \
  --framework terraform_plan \
  --check CKV_AWS_19,CKV_AWS_21,CKV_AZURE_33 \
  --soft-fail-on CHECKOV_CUSTOM_* \
  --compact

Pin Checkov in CI (for example checkov==3.2.x) so rule behaviour does not shift mid-pipeline. Pair this with dedicated IaC scanning guidance from tfsec, Checkov, and Terrascan compared if you want parallel engines for defence in depth.

Step 3: Write custom OPA Rego for rules scanners miss

Generic scanners cannot encode "staging Azure subscriptions may not peer into production AWS VPCs." Rego fills that gap:

# policies/rego/tags.rego
package terraform.tags

deny[msg] {
  resource := input.resource_changes[_]
  resource.change.actions[_] == "create"
  not required_tags(resource)
  msg := sprintf("TAG-001: %s missing required tags", [resource.address])
}

required_tags(resource) {
  tags := resource.change.after.tags
  tags.cost_centre
  tags.environment
  tags.owner
}

Run Conftest against plan JSON or against rendered manifests:

conftest test tfplan.json -p policies/rego/ --all-namespaces

Step 4: Wire the policy gate into GitLab CI or GitHub Actions

A pattern I've used on GitLab CI pipelines mirrors application test gates—policy stage fails the pipeline, merge is blocked:

policy:terraform:
  stage: test
  image: bridgecrew/checkov:latest
  script:
    - terraform init -backend=false
    - terraform plan -out=plan.bin
    - terraform show -json plan.bin > plan.json
    - checkov -f plan.json --framework terraform_plan --quiet
    - conftest test plan.json -p policies/rego/ --output json
  artifacts:
    paths: [plan.json]
    reports:
      junit: checkov-junit.xml

Store policies in the same repository as modules—or a dedicated cloud-governance repo consumed as a submodule—so policy changes get the same review culture as application code.

Step 5: Layer native org policies as runtime backstop

CI can be bypassed by a local terraform apply with stolen credentials. Organisation-level denies close that hole:

  • AWS: Service Control Policies denying s3:PutBucketPublicAccessBlock modifications outside a break-glass role.
  • Azure: Policy initiative requiring Microsoft.Storage/storageAccounts to deny public network access.
  • GCP: Organization Policy constraint constraints/storage.publicAccessPrevention set to enforced.

Native policies are cloud-specific; that is acceptable—they are the seatbelt when PaC in CI is the driver training.

Policy Gate CI/CD FlowPull Requestterraform planCheckov scanOPA ConftestPass → ApplyOIDC federated credsFail → Block mergePR comment with rule IDPost-apply: native SCP / Azure Policy / GCP Org PolicyRuntime deny even if CI was skipped+ AWS Config / Azure Monitor compliance dashboards
Policy-as-code CI pipeline: plan, scan, pass or block—native org policies catch anything that slips through.

How do you govern identity, secrets, and Kubernetes across clouds?

Policy as code is not only Terraform. Three adjacent areas cause multi-cloud incidents as often as misconfigured storage.

Workload identity instead of long-lived keys

CI pipelines that embed AWS access keys and Azure client secrets in GitLab variables violate the same least-privilege principles your IAM policies preach. Federated OIDC from GitHub Actions or GitLab to each cloud provider lets apply jobs assume short-lived roles. That pattern is documented in depth under workload identity federation without long-lived keys; treat absence of static cloud keys as policy IAM-001 and scan for them with Gitleaks in the same pipeline.

Secrets governance

Centralise secrets in HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault—and write PaC rules that forbid password = "..." literals in Terraform. On a production Laravel deployment, I've seen database URLs committed in tfvars; a Conftest rule matching password patterns in plan JSON would have blocked it before merge.

Kubernetes admission policies

If you run GKE, AKS, or EKS, OPA Gatekeeper or Kyverno enforce pod security at admission: no privileged containers, required labels, approved registries only. The same Rego skills transfer from Terraform plans to Kubernetes AdmissionReview payloads—one language, two enforcement points.

Governance Coverage LayersIaC Policy (Checkov/OPA)Terraform · OpenTofu · ARM · CFNIdentity Policy (OIDC)No long-lived cloud keys in CISecrets PolicyVault · Secrets Manager · Key VaultK8s Admission (Gatekeeper)Pod security · image registryNative Org Policies (AWS SCP · Azure Policy · GCP Org)Final deny layer · compliance dashboards · audit exports
Full Multi-Cloud Governance and Policy as Code coverage: IaC gates, federated identity, secrets rules, Kubernetes admission, and org-level runtime policies.

What are common mistakes when rolling out multi-cloud governance?

Teams fail less on tooling choice and more on organisational fit. Avoid these patterns:

  • Policy big-bang: Enabling every Checkov rule on day one floods developers with hundreds of failures. Roll out by severity: critical security first, tagging second, optimisation third.
  • No exception workflow: Every org needs time-bound waivers with ticket IDs embedded in policy annotations. Permanent exceptions become undeclared debt.
  • Policies without module fixes: Blocking public S3 buckets while your shared Terraform module still defaults to public-read just trains people to click "retry with override."
  • Ignoring plan-vs-apply gap: Scanning only static .tf files misses computed values. Always scan plan JSON after terraform plan.
  • Separate repos, separate owners: When the platform team owns policies but product teams own modules, PRs stall. Co-locate policy tests with the modules they protect.
  • Cost policies without visibility: Tag enforcement without a FinOps dashboard developers can see breeds resentment. Pair TAG-001 with a weekly cost report filtered by owner.

For smaller Nepali teams running a primary VPS plus one cloud account for backups or CDN, full enterprise governance is overkill—but the same PaC habits pay off when you add a second region or DR environment. Start with secrets scanning and tag rules; expand when monthly cloud spend crosses a threshold you would notice on an NPR credit-card statement (roughly Rs 50,000/month, ~USD 370, is a sensible trigger for formal FinOps gates).

Before vs After Policy as CodeBeforeAfterQuarterly manual auditsFindings fixed weeks laterEvery PR scanned in CINon-compliant code never mergesThree different tag schemasFinOps reports unusableUnified TAG-001 via RegoCross-cloud cost allocation worksAudit = console screenshotsNo reproducible evidence trailGit history + CI artefactsSOC 2 / ISO evidence readyMulti-Cloud Governance and Policy as CodeShift left · enforce consistently · audit from Git
Manual multi-cloud governance versus Policy as Code: faster feedback, consistent tags, and audit-ready evidence from CI pipelines.

Measuring success

Track metrics that executives and engineers both understand:

  1. Policy violation rate per 100 PRs — should fall after module fixes, not because checks are disabled.
  2. Mean time to remediate a failed gate — if it exceeds a day, policies may be too opaque.
  3. Percentage of resources with mandatory tags — reported from cloud asset inventory APIs.
  4. Count of open policy exceptions — more than a handful means standards need revision.

Reference frameworks like the AWS Well-Architected Framework and CIS benchmarks when prioritising which Checkov rules to enable first—they give auditors familiar language even when you run Azure and GCP alongside AWS.

Put Multi-Cloud Governance and Policy as Code into production

Multi-Cloud Governance and Policy as Code is not a one-time compliance project. It is a feedback loop: encode a rule, fail a PR, fix a module, watch violation counts drop, add the next rule. Start with five high-impact policies—public access blocks, mandatory tags, encryption defaults, region allowlists, and no static credentials in IaC—wire them into the same GitLab CI or GitHub Actions pipeline you already use for application tests, and layer native org policies so runtime catches whatever CI misses.

If you are designing a multi-cloud footprint for a SaaS product, legal-tech portal, or eCommerce platform and want governance baked in from the first Terraform module—not bolted on after an audit—get in touch to review your architecture, CI pipeline, and policy baseline before the second cloud account opens.

Frequently Asked Questions

Multi-cloud governance sets consistent rules for security, cost, and compliance across AWS, Azure, GCP, and private cloud. Policy as code writes those rules in version-controlled files evaluated automatically during CI/CD or at deploy time, instead of manual checklists.

When teams use AWS for production, Azure for analytics, and GCP for ML, drift happens fast: open S3 buckets, missing encryption, non-standard tags, and shadow IT. I've seen this on client infrastructure where one account followed GitLab CI standards and another did not. Central governance gives you one enforcement model, audit trail, and remediation path. Without it, compliance audits become spreadsheet archaeology and incident response slows because nobody knows which cloud broke the rule first.

Open Policy Agent with Rego is the most portable choice and integrates with Terraform, Kubernetes admission controllers, and CI pipelines. HashiCorp Sentinel targets Terraform Cloud and Enterprise. Cloud Custodian excels at AWS, Azure, and GCP resource cleanup via YAML policies. For Kubernetes-heavy stacks, Kyverno or Gatekeeper enforce cluster rules. Native tools like AWS Config, Azure Policy, and Google Organization Policy are necessary but not sufficient alone; most mature setups combine OPA or Custodian with cloud-native guardrails.

Open-source stacks like OPA, Cloud Custodian, and GitLab CI cost mainly engineer time: Rs 3–8 lakh (~USD 2,200–5,900) for initial setup. Enterprise platforms like Prisma Cloud or Wiz run Rs 1.5–5 lakh/month (~USD 1,100–3,700) depending on account count.

Start when you have two or more cloud accounts, Terraform or Pulumi in CI, or a compliance deadline approaching. Manual reviews collapse around 10–20 engineers or three cloud providers.

On projects where I use GitLab CI with Deployer 7 on EC2, the same pattern extends to IaC repos: run conftest or OPA against Terraform plans on every merge request, fail the pipeline on violations, and store policies in a dedicated Git repo with CODEOWNERS. Stage checks as plan-time validation before apply. Keep policies small and testable with opa test. Pin OPA and provider versions in CI images. Never run apply without a passed policy gate; that is where misconfigured security groups and public buckets slip through.

OPA is cloud-agnostic Rego policies usable in Kubernetes, Terraform, API gateways, and custom services. Sentinel is Terraform-centric and requires HCP Terraform or Enterprise; policies are HCL-like and tightly coupled to HashiCorp workflows. Native engines like Azure Policy and AWS Organizations SCPs enforce at the control plane but use different syntax per vendor and rarely cover application-level rules. In practice, teams use native policies for account boundaries and OPA or Custodian for cross-cloud consistency and CI validation.

Yes, that is a common first use case. Cloud Custodian policies can require owner, environment, and cost-center tags and auto-remediate untagged resources. OPA rules against Terraform plans can block deploys to unapproved regions like restricting production to ap-south-1 and eastus only. Combine tag enforcement with budget alerts in each cloud billing console. Tagging policies fail silently if not enforced at create time; plan-time checks catch drift before resources exist and are far cheaper to fix than post-deploy cleanup scripts.

Writing hundreds of policies on day one, which causes developer revolt and pipeline fatigue. Enforcing rules only at apply time while skipping plan and merge-request checks. Using different policy repos per team with no shared library. Ignoring exceptions workflow for legacy resources. Not versioning OPA or Terraform in CI, leading to false passes. Treating governance as a security-team-only project without platform engineering buy-in. I've repeatedly seen pipelines go red for weeks because nobody tested Rego policies against real Terraform modules before enabling enforcement.

It converts security requirements into automated gates: no public object storage, encryption required on databases, IAM roles must not allow star actions on star resources, and security groups cannot expose SSH to 0.0.0.0/0. Policies run on every change, not quarterly audits. Combined with Git history, you get evidence for SOC 2 and ISO audits. It does not replace runtime detection; pair plan-time policy with GuardDuty, Defender, or Security Command Center for defense in depth. Policy as code stops bad configs early; runtime tools catch active exploitation.

Maintain an exceptions file, often YAML, listing resource IDs, accounts, expiry dates, and approver. OPA and conftest can read exception data and allow named resources while still blocking new violations. Set hard expiry dates; permanent exceptions become permanent risk. Review quarterly with security and finance. Document business justification. For Terraform-managed legacy, use targeted module refactors rather than blanket waivers. On production systems I've maintained, time-bound exceptions with auto-expiry prevented governance programs from stalling while giving teams a migration runway.

If you run a single VPS or one AWS account with a Laravel app deployed via Deployer, full multi-cloud governance is overkill. When you grow to multiple environments, staging and production across regions, or add Azure for backups while keeping AWS primary, lightweight policy as code pays off. Start with GitLab CI checks on Terraform, required tags, and SSL or firewall rules. Budget Rs 50,000–150,000 (~USD 370–1,100) for a consultant to set up OPA gates rather than Rs 2 lakh plus per month for enterprise CSPM. Match tooling to actual cloud count, not vendor marketing.

Read the OPA or conftest denial message first; vague "policy violation" outputs mean your Rego needs better error strings. Run opa eval or conftest test locally against the saved Terraform plan JSON. Compare provider schema changes; AWS and Azure update resource attributes frequently and policies referencing removed fields fail falsely. Check whether the violation is plan-time versus runtime admission. Temporarily run with --warn instead of --fail only in non-production to isolate the rule. Log policy version and input hash in CI artifacts so you can reproduce the exact failure offline.

IaC defines desired state; governance ensures that state meets organizational rules before apply. Standard flow: terraform plan -out=plan.bin, convert to JSON, run conftest test or OPA against it, then apply only if policies pass. OpenTofu 1.6 plus works the same way. Store policies alongside modules or in a central governance repo consumed as a Git submodule or OCI artifact. Remote state in S3 or Azure Blob should itself be governed: encryption, versioning, and no public access. IaC without policy checks gives you repeatable misconfiguration at scale.

Layer open-source tools: OPA plus conftest in GitLab CI, Cloud Custodian scheduled on a small Ubuntu 22.04 cron VM for remediation, and free native controls like AWS Organizations SCPs and Azure Management Groups. Use Infracost or Open Policy Agent cost rules to block oversized instances. For Kubernetes, Kyverno covers many pod and ingress rules without a paid CSPM. Enterprise platforms like Prisma Cloud or Lacework make sense above roughly 50 accounts or strict regulated-industry mandates. Most Nepal agencies and SMBs get 80% of the value from CI-integrated OPA and disciplined tagging at a fraction of enterprise licensing cost.

Share this article

Quick Contact Options
Choose how you want to connect me: