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

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 APIAAP 2.6 Architecture and Components: Complete GuideAAP 2.6 Security Best PracticesAAP 2.6 Self-Service Automation PortalAAP 2.6 Credential Management: Vaults, External Secrets, and Machine Credentials

Category: troubleshooting

Browse all Ansible tutorials · AnsiblePilot Home