> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omni.co/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.omni.co/feedback

```json
{
  "path": "/guides/connections/enforce-database-rbac",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Enforce database RBAC in Omni with connection environments

> Use database-level roles to manage data access, audit logging, and resource allocation in Omni.

export const categoryIcons = {
  'administration': 'lock',
  'api': 'terminal',
  'connections': 'database',
  'dashboards': 'table-columns',
  'embed': 'code',
  'errors': 'exclamation',
  'modeling': 'wrench',
  'patterns': 'plus',
  'schedules & alerts': 'envelope',
  'visualizations': 'chart-column',
  'workbooks': 'book'
};

export const GuideSidebar = ({category, relatedLinks, updatedDate}) => {
  const [progress, setProgress] = React.useState(0);
  React.useEffect(() => {
    const sidebar = document.querySelector('.guide-sidebar');
    if (!sidebar) return;
    let container = sidebar.parentElement;
    while (container && !container.querySelector('.guide-header')) {
      container = container.parentElement;
    }
    if (container && !container.classList.contains('guide-page-layout')) {
      container.classList.add('guide-page-layout');
    }
  }, []);
  React.useEffect(() => {
    const handleScroll = () => {
      const scrollTop = window.scrollY;
      const docHeight = document.documentElement.scrollHeight - window.innerHeight;
      const scrollPercent = docHeight > 0 ? scrollTop / docHeight * 100 : 0;
      setProgress(Math.min(100, Math.max(0, scrollPercent)));
    };
    window.addEventListener('scroll', handleScroll, {
      passive: true
    });
    handleScroll();
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);
  const icon = category ? categoryIcons[category.toLowerCase()] || 'book' : 'book';
  return <aside className="guide-sidebar">
      <div className="guide-sidebar-content">
        <a href="/guides" className="guide-sidebar-back">
          <Icon icon="arrow-left" iconType="solid" size={14} />
          <span>All guides</span>
        </a>

        <div className="guide-sidebar-section">
          <div className="guide-sidebar-label">Progress</div>
          <div className="guide-sidebar-progress">
            <div className="guide-mascot">
              <svg viewBox="0 0 450 450" width="48" height="48">
                <defs>
                  <clipPath id="progressClip">
                    <rect x="0" y={450 - progress * 4.5} width="450" height={progress * 4.5} />
                  </clipPath>
                  <linearGradient id="blobbyGradient" x1="55.9753" y1="0" x2="492.197" y2="169.724" gradientUnits="userSpaceOnUse">
                    <stop stopColor="#BCA2F3" />
                    <stop offset="0.572917" stopColor="#FF7AA2" />
                    <stop offset="1" stopColor="#F3D4A2" />
                  </linearGradient>
                </defs>

                {}
                <circle cx="223.901" cy="223.901" r="213.901" transform="matrix(-0.999988 -0.0049013 0.00491945 -0.999988 447.797 449.992)" fill="#FAFAFA" stroke="#480B38" strokeWidth="20" />

                {}
                <circle cx="223.901" cy="223.901" r="213.901" transform="matrix(-0.999988 -0.0049013 0.00491945 -0.999988 447.797 449.992)" fill="url(#blobbyGradient)" stroke="#480B38" strokeWidth="20" clipPath="url(#progressClip)" />

                {}
                <path d="M310.41 195.084C310.41 200.052 301.362 212.472 284.328 212.472C266.585 212.472 258.246 201.294 258.246 195.912" stroke="#480B38" strokeWidth="17.3883" strokeMiterlimit="1.33344" strokeLinecap="round" />
                <circle cx="21.168" cy="21.168" r="21.168" transform="matrix(-1 0 0 1 388.658 169.001)" fill="#480B38" />
                <circle cx="21.168" cy="21.168" r="21.168" transform="matrix(-1 0 0 1 223.467 169.001)" fill="#480B38" />
              </svg>
            </div>
            <span className="guide-sidebar-progress-text">{Math.round(progress)}%</span>
          </div>
        </div>

        {category && <div className="guide-sidebar-section">
            <div className="guide-sidebar-label">Category</div>
            <div className="guide-sidebar-category">
              <Icon icon={icon} iconType="solid" size={14} />
              <span>{category}</span>
            </div>
          </div>}

        {updatedDate && <div className="guide-sidebar-section">
            <div className="guide-sidebar-label">Last updated</div>
            <div className="guide-sidebar-date">{updatedDate}</div>
          </div>}

        {relatedLinks && relatedLinks.length > 0 && <div className="guide-sidebar-section">
            <div className="guide-sidebar-label">Related</div>
            <ul className="guide-sidebar-links">
              {relatedLinks.map((link, index) => <li key={index}>
                  <a href={link.href}>{link.title}</a>
                </li>)}
            </ul>
          </div>}
      </div>
    </aside>;
};

export const GuideTitle = ({title}) => {
  return <div className="guide-header">
      <h1 className="guide-title">{title}</h1>
    </div>;
};

<GuideSidebar
  categoryIcons={categoryIcons}
  category="connections"
  updatedDate="March 2026"
  relatedLinks={[
{ title: "Connection setup", href: "/connect-data/setup" },
{ title: "User attributes", href: "/administration/users/attributes" },
{ title: "Dynamic environments", href: "/connect-data/dynamic-environments" }
]}
/>

<GuideTitle title="Enforce database RBAC in Omni with connection environments" />

If your organization manages data access through database-level role-based access control (RBAC), you can enforce that same security model in Omni. By mapping each database role to a separate Omni connection and using [dynamic environments](/connect-data/dynamic-environments) with [user attributes](/administration/users/attributes), queries execute under the correct database role for each user — without requiring multiple models.

This approach assumes the underlying data structure is the same across all roles. Individual roles may have access to a subset of the data, but none should reference objects outside the primary connection's schema.

## Benefits

* **Row-level security**: Database policies applied to each role are enforced automatically, since Omni queries run as the connection's database user.
* **Audit logging**: Database logs reflect which role executed each query, providing a clear trail for compliance.
* **Resource management**: Assign different compute warehouses or resource pools to specific roles to manage performance and cost.

## Prerequisites

* Administrative access to your database to create roles and service accounts
* **Organization Admin** permissions in Omni

## Steps

<Steps>
  <Step title="Create the primary connection" titleSize="h3">
    Create a connection using credentials for the **most permissive role** — the one that is a superset of all other roles you plan to use. This connection will serve as the base for your model.

    Refer to the [Database setup guides](/connect-data/setup) for instructions specific to your data warehouse.
  </Step>

  <Step title="Create a connection for each additional role" titleSize="h3">
    For every additional database role you want to map, create a separate Omni connection using that role's service account credentials.

    Each connection must be the **same database type** as the primary connection. The schemas should be structurally identical — if a model references an object that doesn't exist in a role's connection, queries for users on that connection will fail.
  </Step>

  <Step title="Add role connections as environments" titleSize="h3">
    1. Navigate to the **primary connection's** settings page.
    2. Click the **Environments** tab.
    3. Click **New Environment** and select one of the role connections you created in the previous step.
    4. Repeat for each additional role connection.
    5. Click **Save**.

    For more details, see [Dynamically switching database environments](/connect-data/dynamic-environments).
  </Step>

  <Step title="Create the user attribute" titleSize="h3">
    Create a [user attribute](/administration/users/attributes) that will map each Omni user to their database role:

    1. Navigate to **Settings > Attributes**.
    2. Click **New Attribute**.
    3. Choose a **Reference** name that describes the role mapping (for example, `db_role`). You'll use this reference name when configuring the connection in the next step.
    4. Set a **Default Value** that corresponds to the primary connection's role, so users without an explicit assignment fall back to the default.
    5. Click **Save**.

    <Warning>
      Be careful when setting the default value. The default role determines what data unassigned users can access.
    </Warning>

    Then assign the appropriate value to each user. This can be done:

    * **Manually** in **Settings > Attributes > Users** tab
    * **Via the API** using the [User attributes API](/api)
    * **Via SCIM** through an identity provider like Okta, which can sync role assignments automatically
  </Step>

  <Step title="Enable dynamic environment assignment" titleSize="h3">
    1. Navigate back to the primary connection's **Environments** tab.
    2. Toggle **Allow environments to be assigned dynamically** to on.
    3. In the **User attribute** field, enter the reference name of the user attribute you created in the previous step.
    4. In the **Values for the default connection** field, enter the value that maps to the primary connection.
    5. For each environment connection, enter the user attribute value that should route users to that connection.
    6. Click **Update**.
  </Step>

  <Step title="Clean up extra models" titleSize="h3">
    When you created the additional connections in step 2, Omni may have auto-generated a model for each one. Since all roles share the primary connection's model, delete any models that were created for the non-primary connections.

    1. Navigate to **Settings > Connections**.
    2. Click the connection for one of the non-primary roles.
    3. If a model was auto-generated, click **Delete model** on the connection's settings page.
    4. Repeat for each non-primary connection.
  </Step>
</Steps>

## Next steps

* Verify the setup by [impersonating](/administration/users/impersonate) a user with a non-default role and running a test query
* Review your data models to confirm they don't reference objects that are unavailable to restricted roles
* If using an identity provider, configure SCIM to automatically sync role assignments as users are provisioned
