Pull-Based vs. Push-Based Deploys¶
Module 15 (CI/CD) covers a pipeline that builds, tests, and deploys a change — typically by pushing it out: a runner authenticates to the target environment and applies the change from outside. GitOps flips that direction. This page covers exactly what changes when a deploy becomes pull-based.
TL;DR — in 30 seconds:
- Push-based (traditional CI/CD): a pipeline runner, outside the target environment, authenticates in and applies the change — the runner needs deploy credentials to the target.
- Pull-based (GitOps): an operator running inside the target environment pulls the desired state from git and applies it locally — nothing outside the environment needs deploy credentials to it.
- The practical payoff is a smaller credential attack surface: a compromised CI runner in a push model can deploy directly; in a pull model, the worst it can do is merge a bad change to git, which still goes through review and the operator's own reconciliation.
1. Two directions, one goal¶
flowchart LR
subgraph Push["Push-based (traditional CI/CD)"]
P1["CI runner"] -->|"authenticates in,<br/>applies change"| P2["Target environment"]
end
subgraph Pull["Pull-based (GitOps)"]
G1["Git repo"] <-.->|"operator pulls,<br/>compares, applies"| G2["Operator<br/>(inside target environment)"]
end
Both models want the same outcome — the target environment matches the intended change. The difference is who initiates the connection and who holds the credentials:
| Push-based CI/CD | Pull-based GitOps | |
|---|---|---|
| Who applies the change | The CI runner, from outside | An operator, running inside the target |
| Where deploy credentials live | On the CI runner / pipeline | Only inside the target environment |
| What a compromised pipeline can do | Deploy directly to the target | Merge a change to git (still reviewable) |
| How you know what's live right now | Check pipeline logs / history | Read the git repo |
2. Why the credential difference matters¶
In a push model, the CI system needs standing credentials that can write to production — that's a real, valuable target: if the pipeline (or its secrets) is compromised, an attacker can deploy directly.
In a pull model, the operator's credentials never leave the target environment — nothing external holds a key that can write to it. A compromised CI pipeline can still merge a malicious change to the GitOps repo, but that merge is a normal, reviewable git operation (a PR, a diff, a commit author) — not a silent direct deploy. It doesn't eliminate risk, but it narrows what a compromised pipeline can do and makes the action visible in git history.
Common gotchas
- Assuming pull-based means "no CI/CD is involved." Fix: CI/CD still builds, tests, and — in a GitOps flow — opens the PR that updates the desired state in git. What moves is the deploy step, not the whole pipeline.
- Giving the GitOps operator broader permissions than it needs. Fix: pull-based reduces external credential exposure, but the in-cluster operator itself still needs scoped, least-privilege access to the resources it manages — it's not a free pass to over-permission it.
Check yourself — in a push-based pipeline, a stolen CI secret lets an attacker deploy directly to production. What's different about the equivalent attack in a pull-based GitOps setup?
A stolen CI secret in a pull-based setup doesn't grant deploy access to the target environment at all — the CI pipeline never held those credentials. The attacker's best option is merging a malicious change to the GitOps repo, which still goes through the same review/PR process as any other change and is visible in git history, rather than an invisible direct deploy.
Done when: you can state, in one sentence, which side holds the deploy credentials in each model and why that difference narrows what a compromised pipeline can do.