AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

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

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

See also: Ansible Automation Platform RBAC: Role-Based Access Control for Enterprise Teams

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

SettingPurpose
max_hostsLimit total managed hosts per org
default_environmentDefault EE for job templates
custom_virtualenvLegacy venv path (deprecated)

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

RoleScopeCapabilities
System AdministratorGlobalFull access to everything
System AuditorGlobalRead-only access to everything
Normal UserPer-resourceAccess based on granted roles

Resource Roles

Each resource type has specific roles:

ResourceAvailable Roles
OrganizationAdmin, Member, Read, Execute, Project Admin, Inventory Admin, Credential Admin, Workflow Admin, Notification Admin, Audit
Job TemplateAdmin, Execute, Read
Workflow TemplateAdmin, Execute, Approve, Read
InventoryAdmin, Use, Ad Hoc, Update, Read
CredentialAdmin, Use, Read
ProjectAdmin, 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: Centralized RBAC with the Gateway API in AAP 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"

See also: Ansible Automation Platform Upgrade Guide: Migration Path from AAP 2.4 and 2.5 to 2.6

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.

Category: troubleshooting

Browse all Ansible tutorials · AnsiblePilot Home