AAP 2.6 Multi-Tenancy: Organizations, Teams, and RBAC at Scale
By Luca Berton · Published 2024-01-01 · Category: troubleshooting
Implement multi-tenancy in AAP 2.6 with organizations, teams, role-based access control, and resource isolation.
Why Multi-Tenancy in AAP?
Large organizations run a single AAP deployment shared across multiple business units, teams, and projects. Multi-tenancy ensures: • Resource isolation — Team A cannot access Team B's credentials or inventories • Self-service — Teams manage their own automation without platform admin help • Cost efficiency — One platform instead of many • Centralized governance — Consistent policies, auditing, and compliance • Scalability — Add teams without redeploying infrastructure
See also: Ansible Automation Platform RBAC: Role-Based Access Control for Enterprise Teams
AAP Multi-Tenancy Model
AAP uses a hierarchical model:
Platform (Global)
├── Organization: Engineering
│ ├── Team: Backend
│ │ ├── Users: alice, bob
│ │ └── Permissions: Job Templates A, B
│ ├── Team: Frontend
│ │ ├── Users: carol, dave
│ │ └── Permissions: Job Templates C, D
│ ├── Credentials (org-scoped)
│ ├── Inventories (org-scoped)
│ └── Projects (org-scoped)
├── Organization: Operations
│ ├── Team: SRE
│ ├── Team: Network
│ └── Team: Security
└── Organization: Data Science
└── Team: ML Platform
Organizations
Organizations are the top-level tenant boundary. Each organization has its own: • Users and teams • Projects and inventories • Credentials • Job templates and workflows • Notification templates • Execution environments
Create Organizations
- name: Create engineering organization
ansible.platform.organization:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "Engineering"
description: "Software engineering teams"
max_hosts: 500 # Host limit for this org
default_environment: "ee-supported-rhel9"
state: present
- name: Create operations organization
ansible.platform.organization:
name: "Operations"
description: "Infrastructure and operations teams"
max_hosts: 2000
state: present
- name: Create data science organization
ansible.platform.organization:
name: "Data Science"
description: "ML and data engineering teams"
max_hosts: 200
state: present
Organization-Level Settings
| Setting | Purpose |
|---------|---------|
| max_hosts | Limit total managed hosts per org |
| default_environment | Default EE for job templates |
| custom_virtualenv | Legacy venv path (deprecated) |
See also: Centralized RBAC with the Gateway API in AAP 2.6
Teams
Teams group users within an organization:
- name: Create backend team
ansible.platform.team:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "Backend"
organization: "Engineering"
description: "Backend application development team"
state: present
- name: Create SRE team
ansible.platform.team:
name: "SRE"
organization: "Operations"
description: "Site reliability engineering"
state: present
- name: Create network team
ansible.platform.team:
name: "Network"
organization: "Operations"
description: "Network operations and automation"
state: present
Add Users to Teams
- name: Add alice to backend team
ansible.platform.role:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
role: "Member"
team: "Backend"
user: "alice"
state: present
RBAC Roles
AAP uses a granular role system. Every resource has associated roles:
System Roles
| Role | Scope | Capabilities | |------|-------|-------------| | System Administrator | Global | Full access to everything | | System Auditor | Global | Read-only access to everything | | Normal User | Per-resource | Access based on granted roles |
Resource Roles
Each resource type has specific roles:
| Resource | Available Roles | |----------|----------------| | Organization | Admin, Member, Read, Execute, Project Admin, Inventory Admin, Credential Admin, Workflow Admin, Notification Admin, Audit | | Job Template | Admin, Execute, Read | | Workflow Template | Admin, Execute, Approve, Read | | Inventory | Admin, Use, Ad Hoc, Update, Read | | Credential | Admin, Use, Read | | Project | Admin, Use, Update, Read |
Grant Permissions
# Grant team permission to execute a job template
- name: Allow backend team to run deploy template
ansible.platform.role:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
role: "Execute"
job_template: "Deploy Backend App"
team: "Backend"
state: present
# Grant team inventory use permission
- name: Allow SRE to use production inventory
ansible.platform.role:
role: "Use"
inventory: "Production Servers"
team: "SRE"
state: present
# Grant team credential use permission
- name: Allow network team to use network credentials
ansible.platform.role:
role: "Use"
credential: "Network SSH Key"
team: "Network"
state: present
# Grant org admin role
- name: Make alice an org admin for Engineering
ansible.platform.role:
role: "Admin"
organization: "Engineering"
user: "alice"
state: present
See also: Ansible Automation Platform Upgrade Guide: Migration Path from AAP 2.4 and 2.5 to 2.6
Multi-Tenancy Design Patterns
Pattern 1: Org per Business Unit
Each business unit gets its own organization:
organizations:
- name: "Retail"
teams: ["Store Ops", "E-Commerce", "Supply Chain"]
max_hosts: 1000
- name: "Finance"
teams: ["Trading", "Risk", "Compliance"]
max_hosts: 500
- name: "HR"
teams: ["Payroll", "Recruitment"]
max_hosts: 200
Pros: Strong isolation, clear ownership Cons: Shared resources (like monitoring playbooks) must be duplicated
Pattern 2: Org per Environment
Separate organizations for dev, staging, and production:
organizations:
- name: "Development"
teams: ["All Developers"]
max_hosts: 500
- name: "Staging"
teams: ["QA", "DevOps"]
max_hosts: 200
- name: "Production"
teams: ["SRE", "On-Call"]
max_hosts: 2000
Pros: Environment isolation, different credential sets Cons: Same team needs access to multiple orgs
Pattern 3: Shared Services Org
A central "Platform" org provides shared resources to all tenants:
organizations:
- name: "Platform" # Shared by all
resources:
- projects: ["compliance-playbooks", "monitoring-playbooks"]
- credentials: ["Vault Lookup", "Satellite"]
- inventories: ["All Servers (Dynamic)"]
- name: "App Team A"
uses_from_platform: ["compliance-playbooks", "Vault Lookup"]
- name: "App Team B"
uses_from_platform: ["compliance-playbooks", "monitoring-playbooks"]
LDAP/SAML Integration
Map external directory groups to AAP organizations and teams:
LDAP Group Mapping
# Configure via Controller settings API
- name: Configure LDAP team mapping
ansible.builtin.uri:
url: "https://gateway.example.org/api/controller/v2/settings/ldap/"
method: PATCH
headers:
Authorization: "Bearer {{ token }}"
Content-Type: "application/json"
body_format: json
body:
AUTH_LDAP_TEAM_MAP:
Backend:
organization: "Engineering"
users: "CN=Backend Developers,OU=Groups,DC=example,DC=com"
remove: true
SRE:
organization: "Operations"
users: "CN=SRE Team,OU=Groups,DC=example,DC=com"
remove: true
AUTH_LDAP_ORGANIZATION_MAP:
Engineering:
admins: "CN=Eng Leads,OU=Groups,DC=example,DC=com"
users: "CN=All Engineers,OU=Groups,DC=example,DC=com"
remove_users: true
remove_admins: true
SAML Group Mapping
AUTH_SAML_TEAM_ATTR:
team_attr: "memberOf"
team_org_map:
- team: "Backend"
organization: "Engineering"
saml_attr: "CN=backend-devs"
- team: "SRE"
organization: "Operations"
saml_attr: "CN=sre-team"
Instance Groups for Tenant Isolation
Assign dedicated execution nodes to organizations:
# Create org-specific instance group
- name: Create Engineering instance group
ansible.platform.instance_group:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "engineering-exec"
policy_instance_minimum: 2
state: present
# Assign instance group to organization
- name: Assign instance group to Engineering org
ansible.platform.organization:
name: "Engineering"
instance_groups:
- "engineering-exec"
state: present
This ensures Engineering jobs only run on dedicated execution nodes, providing: • Performance isolation — other orgs can't consume Engineering's capacity • Network isolation — Engineering exec nodes can be in a specific network zone • Compliance — certain workloads must run on dedicated infrastructure
Auditing Multi-Tenant Activity
Activity Stream Filtering
# View all activity for a specific organization
curl -s -k -H "Authorization: Bearer $TOKEN" \
"https://gateway.example.org/api/controller/v2/organizations/3/activity_stream/" | \
jq '.results[] | {timestamp: .timestamp, user: .summary_fields.actor.username, action: .operation, object: .object1}'
# View all failed jobs for an organization
curl -s -k -H "Authorization: Bearer $TOKEN" \
"https://gateway.example.org/api/controller/v2/jobs/?status=failed&job_template__organization=3" | \
jq '.results[] | {id: .id, name: .name, started: .started}'
Compliance Reporting
- name: Generate multi-tenant compliance report
hosts: localhost
tasks:
- name: Get all organizations
ansible.builtin.uri:
url: "{{ gateway_url }}/api/controller/v2/organizations/"
headers:
Authorization: "Bearer {{ token }}"
register: orgs
- name: Get job stats per org
ansible.builtin.uri:
url: "{{ gateway_url }}/api/controller/v2/jobs/?job_template__organization={{ item.id }}&finished__gte={{ lookup('pipe', 'date -d \"-30 days\" +%Y-%m-%d') }}"
headers:
Authorization: "Bearer {{ token }}"
loop: "{{ orgs.json.results }}"
register: org_jobs
- name: Report
ansible.builtin.debug:
msg: "Org: {{ item.item.name }} | Jobs (30d): {{ item.json.count }}"
loop: "{{ org_jobs.results }}"
FAQ
Can users belong to multiple organizations?
Yes. A user can be a member of multiple organizations and teams. Their effective permissions are the union of all granted roles across all organizations.
Can I prevent org admins from creating credentials?
Yes. Use the Credential Admin role instead of Admin. Org Admin has full access within the org, but you can create more granular roles by assigning specific resource-level roles instead of org-level Admin.
How do I share a project across organizations?
Create the project in a shared "Platform" organization and grant Use permission to teams in other organizations. Alternatively, create the same project in each organization (pointing to the same Git repo).
What is the maximum number of organizations?
There is no hard limit. Practical limits depend on database size and management complexity. Most enterprise deployments have 5-50 organizations.
Can I set quotas per organization?
The max_hosts setting limits the number of managed hosts per organization. There are no built-in quotas for job count, storage, or API calls. Implement custom quotas via API monitoring and alerting.
Conclusion
Multi-tenancy in AAP 2.6 enables a single automation platform to serve an entire enterprise. The combination of organizations, teams, RBAC roles, instance groups, and directory integration provides the isolation, self-service, and governance that shared platforms require. Design your tenant model early — reorganizing later is significantly harder than getting it right from the start.
Related Articles
• AAP 2.6 RBAC and Gateway API • AAP 2.6 Architecture and Components: Complete Guide • AAP 2.6 Security Best Practices • AAP 2.6 Self-Service Automation Portal • AAP 2.6 Credential Management: Vaults, External Secrets, and Machine CredentialsCategory: troubleshooting