Workspace ·DarDev Team · 5 min read

Zero-trust IAM for internal SaaS

How DarDev applies zero-trust identity to internal admin tools—Twenty CRM, Listmonk, GitLab, Grafana—on a single VPS without shared passwords or cluster-admin CI tokens.

Platform engineer reviewing identity flows between internal admin applications

Zero-trust IAM for internal SaaS means every admin login, API call, and background job proves identity and authorization—even when traffic never leaves your VPC. A CRM, mailer console, GitLab instance, and Grafana board on the same dardev-vps are still separate attack surfaces: a stolen Listmonk session should not imply Grafana admin, and a CI token must not mount cluster secrets by default.

DarDev runs internal tooling from shared Kubernetes on one OVH host—Twenty CRM, Listmonk, Stalwart admin, sync workers, GitLab, and Grafana. Workspace is our Authorize layer for OIDC and group mapping. This guide documents zero-trust IAM at that scale, not an enterprise seat-count checklist.

What counts as internal SaaS at DarDev scale

Internal SaaS here means browser-based tools your operators use daily, backed by containers and Postgres, not desktop scripts on one laptop. Customer-facing products—Hesabi, DarDevLab, EscaHire on waitlist—have their own tenancy models described in identity-multi-tenant-platforms. Internal apps share infrastructure but must not share credentials.

  • Human-facing admin UIs: CRM, campaign mailer, MTA console, news CMS
  • Platform engineering: GitLab, Grafana, ingress dashboards
  • Machine-facing integrations: Twenty→Listmonk sync worker, deploy hooks, backup jobs
  • Break-glass paths for platform owners with stronger audit than everyday login

At five to fifteen operators on one cluster, prioritize explicit trust boundaries over another identity appliance. See workspace-authorize-step for where Authorize sits in our pipeline.

Zero-trust principles we actually enforce

Zero trust means authenticate every request, least privilege, assume breach, and auditable logs. On a Tunisia VPS that is short-lived sessions, scoped service principals, NetworkPolicy between namespaces, and no trust from internal IP alone.

  1. Verify explicitly — OIDC for humans; scoped tokens or mTLS for service-to-service
  2. Least privilege — RBAC roles per app; CI jobs get deploy scope, not cluster-admin
  3. Assume breach — rotate secrets, revoke sessions centrally, alert on break-glass use
  4. Log and correlate — same request_id or subject ID from ingress through worker logs

Human access: one IdP, many apps

Operators sign in once through Workspace OIDC and land in GitLab or Grafana with group-derived roles. sso-gitlab-grafana-apps covers redirect URIs, group sync, and logout tests before SSO on a new admin tool.

  1. Register the app as an OIDC client

    Store client ID and secret in sealed secrets or your vault pattern—not in the app git repo. Pin redirect URIs to HTTPS hostnames behind host nginx.

  2. Map groups to roles

    Platform, marketing, and read-only CRM views get distinct IdP groups. Avoid a single admins group that unlocks every namespace.

  3. Set session lifetime

    Shorter for high-risk consoles (MTA, CRM exports); longer only where UX truly needs it and MFA is enforced upstream.

  4. Test logout and revocation

    Offboarding must kill sessions without waiting for idle timeout. session-security-admin-tools covers cookie flags and admin-session hardening.

Machine access: workers and CI

Background jobs are where zero-trust IAM for internal SaaS usually fails first. A sync worker that mirrors Twenty contacts into Listmonk must use an API key or OAuth client scoped to those two APIs—not a human admin cookie copied into an environment variable. GitLab CI must deploy with a project token or impersonation limited to one namespace, not a kubeconfig cut from cluster-admin.

Grant Postgres read on the tables a script touches, not superuser. Rotate machine credentials with TLS certs and name owners in runbooks.

Network and service boundaries inside the cluster

Default-deny NetworkPolicy between namespaces forces east-west traffic through known services. Ingress stays TLS at nginx; admin UIs never sit on public ports without auth. A service mesh is optional—NetworkPolicy plus mTLS on sensitive paths is enough before Istio ops cost pays off.

  • Sync worker namespace may reach Twenty and Listmonk APIs; not GitLab shell
  • Grafana queries Prometheus; it does not need CRM database credentials
  • Break-glass kubectl access is separate from application service accounts
  • Document which namespaces may initiate SMTP toward Stalwart

Phased rollout for a small platform team

Week one: inventory internal URLs and.env keys. Week two: OIDC GitLab or Grafana through Workspace. Week three: replace the worst shared CI or worker password with a scoped principal. Week four: NetworkPolicy on mailer and CRM namespaces. Defer SAML until a contract requires it.

Mistakes we fix in client audits

  • Cluster-admin kubeconfig in GitLab CI variables
  • One Listmonk admin password shared in Slack
  • Trusting internal IP alone for metrics or debug endpoints
  • Service accounts that never rotate because nobody owns the runbook
  • SSO enabled without testing group removal on offboarding day one
Flow diagram from OIDC identity provider through Workspace to internal admin applications
Humans federate through Workspace; machines use scoped credentials per integration.

How Workspace helps

Workspace centralizes OIDC, group sync into GitLab and Grafana, and patterns for new admin tools. See dardev.net/products or mail.dardev.net/subscribe/workspace-marketing.html for Workspace updates.

Do we need a service mesh for zero-trust internal SaaS?

Not on one cluster at our scale. Start with OIDC, scoped worker tokens, NetworkPolicy, and TLS at ingress. Add a mesh when east-west mTLS is weekly ops pain.

How is internal IAM different from customer multi-tenant identity?

Customer products need org-scoped data isolation and billing boundaries. Internal SaaS needs operator RBAC and integration credentials that never double as customer sessions. The IdP may be shared through Workspace, but authorization models stay separate per app.

What should we lock down first on dardev-vps?

Revoke cluster-admin CI tokens, rotate any shared admin password in Listmonk or CRM, and put GitLab behind OIDC with group mapping. Those three changes remove the highest-impact blast radius before you tune session timeouts.

Can internal tools share one Postgres role?

No. Each application and worker gets credentials limited to its database and schema. Shared superuser roles defeat audit and make credential rotation a big-bang outage.

Where do we go deeper on sessions and SSO?

session-security-admin-tools for admin-session hardening; sso-gitlab-grafana-apps for group sync; identity-multi-tenant-platforms when operators also touch customer tenant data.

Get company news

Releases and announcements — confirm from your inbox.

Subscribe to updates