Overview#
Give every tenant its own ArgoCD AppProject — scoped to the tenant's namespaces, with owner, edit and view roles — derived from the Tenant you already maintain and kept in sync as it changes.
Note
This is the Helm-chart ArgoCD extension (mto-extension-argocd). It replaces the built-in ArgoCD integration configured through the Extensions resource, now deprecated — see the older integration and Migrating.
Requires Template Operator v2
The extension is configuration for Template Operator v2 (custom resources in the templates.v2.stakater.com API group) — it installs no controller of its own and does nothing until Template Operator v2 reconciles it. Template Operator v2 must be running on the cluster; MTO can deploy it for you. See Installation.
At a glance#
| You maintain | The extension keeps in sync |
|---|---|
a Tenant |
one AppProject per tenant |
| and opt it in (one annotation) | scoped to the tenant's namespaces |
| owner / edit / view roles, bound to its groups and users | |
| the repositories it may deploy from | |
| the cluster-scoped kinds it may manage |
You write — a Tenant, opted in:
apiVersion: tenantoperator.stakater.com/v1beta3
kind: Tenant
metadata:
name: acme
annotations:
argocd.tenantoperator.stakater.com/enabled: "true" # opt in
spec:
accessControl:
owners:
groups: [acme-admins]
users: [alice@acme.example]
namespaces:
withTenantPrefix: [dev, prod]
You get — one AppProject, kept in sync (abridged):
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: acme
namespace: openshift-gitops
spec:
destinations: # the tenant's namespaces — never the control plane
- { namespace: acme-dev, server: https://kubernetes.default.svc }
- { namespace: acme-prod, server: https://kubernetes.default.svc }
roles: # bound to the tenant's groups and users
- { name: acme-owner, ... } # full access to acme/*
- { name: acme-edit, ... } # get, sync, update
- { name: acme-view, ... } # get
sourceRepos: [ https://github.com/acme/acme-gitops ]
No AppProject YAML and no hand-written ArgoCD RBAC — and nothing is created for a tenant until it opts in.
How it works#
The chart installs no operator of its own. It renders three Template Operator v2 objects — a parent Template, a child Template, and one parent TemplateInstance — and Template Operator v2 reconciles one AppProject per tenant.
flowchart LR
T[Tenants] --> P
N[Namespaces] --> P
IC[IntegrationConfig] --> P
P["parent<br/>TemplateInstance"] -- one child per opted-in tenant --> C["child<br/>TemplateInstance"]
C -- renders --> A["one AppProject<br/>per tenant"]
A --> ARGO[ArgoCD]
The parent reads every Tenant, every Namespace, and the IntegrationConfig — three cluster-wide watches regardless of tenant count — and emits one child per opted-in tenant. A namespace event affecting one tenant rewrites only that tenant's project.
Who does what#
| Platform administrator | Tenant | |
|---|---|---|
| Sets up | installs the chart; sets argocd.namespace, repos, resource limits |
— |
| Per tenant | nothing — opt-in is one annotation | opts in; creates Applications in its project |
| Never | hand-writes an AppProject or ArgoCD RBAC |
touches ArgoCD RBAC, or reaches another tenant's project |
The division is the point: a tenant gets self-service GitOps scoped to itself, and the platform team maintains no per-tenant ArgoCD configuration.
How roles map to ArgoCD access#
Each Tenant access level becomes one AppProject role, at least privilege by default (roles.profile: leastPrivilege):
| Tenant level | ArgoCD role | applications |
applicationsets |
repositories / clusters / logs |
|---|---|---|---|---|
| owners | <tenant>-owner |
full (*) |
full (*) |
get (repos *) |
| editors | <tenant>-edit |
get, sync, update, action/* |
get |
get |
| viewers | <tenant>-view |
get |
get |
get |
Edit cannot create, delete or override Applications, and the web terminal (exec) is off unless you enable it for owners. The legacy, broader shape exists for migration only — see Security and Migrating.
Built on Template Operator
Because the extension renders through Template Operator, the permissions the chart grants are shared with anyone who can author a Template. On a cluster where tenants (or others) can create Templates, read Security → how the extension scopes Template Operator v2 before going to production.
In this section#
- Installation — requirements, install the chart, opt a tenant in
- Giving a tenant an AppProject — opt in, see the
AppProject, deploy an Application - Applications in tenant namespaces — Applications and ApplicationSets outside the control plane
- Identity and sync impersonation — groups by pattern, syncing as a tenant ServiceAccount
- Security — least-privilege defaults, cluster-scoped kinds, the trust boundary
- Operating — drift protection, deletion, fleet health, uninstall
- Reference — chart values and per-tenant overrides
- Migrating — from the deprecated
Extensionsintegration
Next: Installation