Skip to content

feat: allow/deny access policies from Ingress annotations#277

Open
twiechert wants to merge 1 commit intoSTRRL:masterfrom
twiechert:feat/cloudflare-access-groups
Open

feat: allow/deny access policies from Ingress annotations#277
twiechert wants to merge 1 commit intoSTRRL:masterfrom
twiechert:feat/cloudflare-access-groups

Conversation

@twiechert
Copy link
Copy Markdown

@twiechert twiechert commented Feb 24, 2026

Manages Cloudflare Access Applications and their allow/deny policies from Ingress annotations:

cloudflare-tunnel-ingress-controller.strrl.dev/cloudflare-access-allowed-group: "viewers,admins"
cloudflare-tunnel-ingress-controller.strrl.dev/cloudflare-access-denied-group: "contractors"

Groups are referenced by name, resolved to IDs at reconcile time. The annotation is IdP-agnostic — whether groups are backed by Zitadel OIDC claims, Google Workspace groups, or anything else doesn't matter. Ownership tracked via ctic:<tunnel>:<hostname> naming convention (same pattern as _ctic_managed DNS records).

Motivation
With an OIDC provider and Cloudflare Tunnel in place, you can already gate access per service — but the per-hostname Access Applications and policies still need to be managed separately (Terraform, dashboard, API). Adding or removing a service means updating both the Ingress and the access config in another system. This moves it into the Ingress annotation so it stays in one place.

You could also handle authorization natively in the IdP by registering each service as a separate OIDC application with its own role grants — but that means maintaining every service twice: once as an Ingress and again in the IdP.

Add support for managing Cloudflare Access Applications directly from
Kubernetes Ingress annotations, co-locating access policy with the
services it protects.

New annotations:
- cloudflare-access-allowed-group: comma-separated Access Group IDs
  that are allowed access (creates an allow policy)
- cloudflare-access-denied-group: comma-separated Access Group IDs
  that are denied access (creates a higher-precedence deny policy)

When allowed-group is set, the controller creates a self-hosted Access
Application for the hostname with deterministic naming (ctic:<tunnel>:<host>)
for ownership tracking. Applications are reconciled on each sync:
created, updated, or deleted to match the desired state.

This keeps the controller IdP-agnostic — groups encapsulate the
OIDC/email/mTLS logic and are referenced by ID.
@codecov
Copy link
Copy Markdown

codecov bot commented Feb 24, 2026

Codecov Report

❌ Patch coverage is 25.75758% with 147 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.39%. Comparing base (f35a4ea) to head (a853e7d).
⚠️ Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
pkg/cloudflare-controller/access.go 26.11% 133 Missing ⚠️
pkg/controller/transform.go 26.66% 9 Missing and 2 partials ⚠️
pkg/cloudflare-controller/tunnel-client.go 0.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #277      +/-   ##
==========================================
- Coverage   47.08%   42.39%   -4.69%     
==========================================
  Files          11       12       +1     
  Lines         703      901     +198     
==========================================
+ Hits          331      382      +51     
- Misses        349      494     +145     
- Partials       23       25       +2     
Flag Coverage Δ
integration 20.00% <2.02%> (-5.08%) ⬇️
unit 25.17% <23.73%> (-0.43%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@twiechert twiechert marked this pull request as ready for review February 26, 2026 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant