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

# Getting started with data access governance (DAG)

> Learn how DAG complements role-based access control (RBAC) to restrict access to specific resources

export const MintTable = ({columns = [], rows = [], columnWidths = []}) => {
  const pushTextWithLineBreaks = (parts, text, keyBase) => {
    const segments = String(text).split(/\\n|\n/);
    segments.forEach((segment, idx) => {
      if (segment) {
        parts.push(<span key={`${keyBase}-text-${idx}`}>{segment}</span>);
      }
      if (idx < segments.length - 1) {
        parts.push(<br key={`${keyBase}-br-${idx}`} />);
      }
    });
  };
  const parseMarkdown = text => {
    if (text === null || text === undefined) return "";
    const str = String(text);
    const parts = [];
    let lastIndex = 0;
    const pattern = /(`[^`]+`|\*\*[^*]+\*\*|\*[^*]+\*|\[([^\]]+)\]\(([^)]+)\))/g;
    let match;
    while (true) {
      match = pattern.exec(str);
      if (match === null) {
        break;
      }
      if (match.index > lastIndex) {
        pushTextWithLineBreaks(parts, str.substring(lastIndex, match.index), `before-${lastIndex}`);
      }
      const fullMatch = match[0];
      if (fullMatch.startsWith("`") && fullMatch.endsWith("`")) {
        parts.push(<code key={match.index}>{fullMatch.slice(1, -1)}</code>);
      } else if (fullMatch.startsWith("**") && fullMatch.endsWith("**")) {
        parts.push(<strong key={match.index}>{fullMatch.slice(2, -2)}</strong>);
      } else if (fullMatch.startsWith("*") && fullMatch.endsWith("*")) {
        parts.push(<em key={match.index}>{fullMatch.slice(1, -1)}</em>);
      } else if (fullMatch.startsWith("[")) {
        const linkText = match[2];
        const linkUrl = match[3];
        parts.push(<a key={match.index} href={linkUrl} className="text-black-600 dark:text-black-400">
            {linkText}
          </a>);
      }
      lastIndex = pattern.lastIndex;
    }
    if (lastIndex < str.length) {
      pushTextWithLineBreaks(parts, str.substring(lastIndex), `tail-${lastIndex}`);
    }
    if (parts.length > 0) {
      return parts;
    }
    const plainParts = [];
    pushTextWithLineBreaks(plainParts, str, "plain");
    return plainParts.length ? plainParts : str;
  };
  const safeColumns = Array.isArray(columns) ? columns : [];
  const safeRows = Array.isArray(rows) ? rows : [];
  const safeColumnWidths = Array.isArray(columnWidths) ? columnWidths : [];
  const hasColumnWidths = safeColumnWidths.some(w => w !== null && w !== undefined && w !== "");
  const toCssWidth = width => typeof width === "number" ? `${width}px` : String(width);
  const getColumnStyle = idx => {
    const rawWidth = safeColumnWidths[idx];
    if (rawWidth === null || rawWidth === undefined || rawWidth === "") {
      return undefined;
    }
    const width = toCssWidth(rawWidth);
    return {
      width,
      minWidth: width
    };
  };
  const containerStyle = hasColumnWidths ? undefined : {
    overflowX: "auto"
  };
  const tableStyle = hasColumnWidths ? {
    tableLayout: "fixed",
    width: "100%"
  } : {
    width: "max-content",
    minWidth: "100%"
  };
  if (!Array.isArray(columns) || !Array.isArray(rows) || !Array.isArray(columnWidths)) {
    console.warn("MintTable received invalid props:", {
      columns,
      rows,
      columnWidths
    });
  }
  if (!safeColumns.length && !safeRows.length) {
    return null;
  }
  return <div className="mint-table-container" style={containerStyle}>
      <table style={tableStyle}>
        {hasColumnWidths && <colgroup>
            {safeColumns.map((_, idx) => {
    const style = getColumnStyle(idx);
    return <col key={idx} style={style} />;
  })}
          </colgroup>}
        <thead>
          <tr>
            {safeColumns.map((col, idx) => <th key={idx} className="text-left" style={getColumnStyle(idx)}>
                <b>{parseMarkdown(col)}</b>
              </th>)}
          </tr>
        </thead>
        <tbody>
          {safeRows.map((row, rIdx) => {
    const safeRow = Array.isArray(row) ? row : [];
    return <tr key={rIdx}>
                {safeRow.map((cell, cIdx) => <td key={cIdx} style={getColumnStyle(cIdx)}>
                    {parseMarkdown(cell)}
                  </td>)}
              </tr>;
  })}
        </tbody>
      </table>
    </div>;
};

## Overview

This tutorial shows how to use Sift data access governance (DAG) to protect resources such as Assets, Channels, and Runs. In this tutorial, you will:

* Prevent a specific user from viewing an Asset and its Channels.
* Keep the Asset accessible to other authorized users.
* Create an explicit deny policy using DAG.
* Block access to an Asset containing sample satellite telemetry.
* Restrict a user’s existing permissions without changing their role.

## DAG summary

In DAG, users and resources are labeled with attributes. Policies evaluate those attributes to determine whether access should be allowed.

Here's a brief summary of DAG for this tutorial. For a detailed explanation, see the [Data Access Governance (DAG) overview](/documentation/manage/set-up-data-access-governance).

<Accordion title="What is DAG?">
  DAG adds granular access control on top of Sift’s role-based access control (RBAC).

  * Restrict access to specific data without changing a user’s role.
  * Apply security and export controls within the permissions already granted by RBAC.
  * Deny visibility to sensitive data that would otherwise be accessible.
  * Define scalable access policies that automatically apply as users, teams, and data grow.
  * Uses attributes for users and resources to enforce policies.
  * Evaluate these attributes when a user accesses a resource.

  <MintTable
    columns={['Component', 'Definition']}
    rows={[
  [
     'User attribute',
     'A key value label assigned to a user account. It describes who the user is or what they are authorized to do.'
  ],
  [
     'Resource attribute',
     'A key value label assigned to resources such as Assets, Channels, and Runs. Resource attributes can only be assigned directly to Assets, Channels, and Runs.'
  ],
  [
     'Policy',
     'A statement that defines the conditions where access is granted or denied. It checks user and resource attributes during each access request.'
  ]
]}
  />

  You use these three components to allow or deny access to specific data in Sift.

  <div align="center">
    ```mermaid theme={null}
    graph LR
       Start{{"User attempts to view or interact with the Asset"}}:::highlight
       Evaluate{"Policy checks for a match between user and resource attributes"}:::highlight

       Start --> Evaluate
       Evaluate --> Denied("Access restricted by policy"):::denied
       Evaluate --> Granted("Access permitted by policy"):::granted

       classDef highlight fill:#262626,stroke:#ee4220,stroke-width:0px,color:#ffffff;
       classDef granted fill:#e8f5e9,stroke:none,color:#1b5e20;
       classDef denied fill:#ffebee,stroke:none,color:#b71c1c;
       linkStyle default stroke:#262626,stroke-width:1px;
    ```
  </div>
</Accordion>

## Prerequisites

Before you begin, make sure you have the following:

* A general understand of Sift, as covered in the Sift [Learning Path](/learning-path/overview).
* Access to the DAG feature.
  * Access is available only to Admins in organizations where DAG is enabled. If DAG is not enabled for your organization, contact Sift to request access.
* An Asset named `fl_leo` that contains sample Low Earth Orbit (LEO) satellite telemetry data.
  1. Import this [CSV file](https://drive.google.com/file/d/1FWTLYMzxRNRNUESuLgHWBU0HHJsfXlFk/view?usp=share_link) into Sift to create an Asset.
  2. For the Asset name, Replace `fl` in `fl_leo` with your initials. This helps avoid naming conflicts if others are also completing the tutorial on the same Sift instance.
  3. For the Run name, leave the default value.
  4. Do not modify any other settings.

## Step 1: Create a user attribute

In this step, you will:

* Create a user attribute that identifies users who should be denied access to the LEO Asset.
* Define the attribute as a label that DAG policies can evaluate. You will use the attribute later when creating a policy that enforces access restrictions.

1. In **Sift**, click your profile icon, and then select **Manage**.
2. In **Access Control**, click **User Attributes**.
3. Click **Create User Attribute**.
4. In the **Type** list, select **Boolean**.
   <Info>
     Sift supports multiple data types for user and resource attributes. For this user attribute example, we select **Boolean** because we only need a simple `Authorized/Not authorized` flag. To learn more, see [Attribute data types](/documentation/manage/set-up-data-access-governance#attribute-data-types).
   </Info>
5. In the **Name** box, enter: `fl_leo_denied`.
   <Info>
     Replace `fl` in `fl_leo_denied` with your initials (first and last name).
   </Info>
6. In the **Description** box, enter: `Users that should be denied access to the LEO Asset`.
7. Click **Save**.

## Step 2: Assign the user attribute

Next you will assign the new user attribute to the Group whose members should be denied access to the LEO Asset. Assigning the attribute to a Group applies it to every member at once, so you can scale access control without managing users individually. Assigning this attribute does not immediately deny access. It only labels the Group so that a policy can later reference this attribute.

<Info>
  You can also assign user attributes directly to individual users. Groups are recommended because every member inherits the attribute automatically, which keeps policies easy to maintain as your team grows.
</Info>

1. In **Access Control**, click **User Attributes**.
2. In the **User attributes** table, find \***\_leo\_denied**.
3. Click <Icon icon="ellipsis-vertical" /> **Options**, and then select **Assign**.
4. In **Assign User Attributes**, in **Groups**, select a Group whose members should be denied access, and click **Assign**.
   * You can select any Group, but make sure you are not a member of it. You can change this selection later.
   * Once the policy is active, every member of this Group will have their RBAC permissions further limited for this specific Asset. While members might still have a global `View` role, this DAG policy will further restrict it to deny access.
5. In **Assign to 1 group**, set Boolean option to **True**.
   * We selected **True** because the policy you create later will match users where \*\_leo\_denied is true and deny them access. Setting this value to **True** ensures every member of the selected Group matches the policy condition.
6. Click **Next**.
7. Review your changes, and then click **Update**.

At this point, no access has changed. Group members still have the same RBAC roles and permissions as before. Access will only be changed after you create a policy that checks for this attribute in a later step.

Next, you'll create a resource attribute to protect the LEO Asset.

## Step 3: Create a resource attribute

In this step, you will create a resource attribute that identifies the LEO Asset you want to protect. Resource attributes describe what a resource is and allow DAG policies to target specific Assets, Channels, or Runs.

<Info>
  Creating the resource attribute at this point does not change access because resource attributes only take effect when they are referenced by a policy.
</Info>

1. In **Access Control**, click **Resource Attributes**.
2. Click **Create Resource Attribute**.
3. In **Type**, select **Enum**.
4. In **Name**, enter: `fl_leo_asset`.
   <Info>
     Replace `fl` in `fl_leo_asset` with your initials (first and last name).
   </Info>
5. In **Description**, enter: `Identifies the LEO Asset protected by DAG`.
6. In **Value Options**, enter: `leo`.
7. Click **Save**.

## Step 4: Assign the resource attribute to the Asset

Now that you have created the `*_leo_asset` resource attribute, you must apply it to the LEO Asset.

<Accordion title="Understanding access inheritance">
  DAG enforces access inheritance between related resources. By assigning the attribute to the Asset, you protect the Asset and its related data without tagging each resource individually.

  * **Channels:** If a user is denied an action on an asset, the same action is automatically denied on all channels belonging to that asset. Denying `viewDetails` on the Asset removes both the Asset and all of its Channels from the user's view.
  * **Runs:** Access inheritance for runs applies only to viewing telemetry data (`viewData`). To view data on a run, the user must have `viewData` access to at least one of the run's associated assets. Other actions on runs (such as editing details) are evaluated on the run independently.
    For this tutorial, denying `viewDetails` on the Asset is sufficient — it hides the Asset and its Channels from the restricted user.
</Accordion>

1. In **Access Control**, click **Resource Attributes**.
2. In **Resource Attributes**, find \***\_leo\_asset**.
3. Click <Icon icon="ellipsis-vertical" /> **Options**, then select **Assign**.
4. In search field, enter the name of the LEO Asset you created (for example, `*_leo`).
5. In the search results, select your LEO Asset.
6. Click **Assign**.
7. In **Enum**, select **leo**.
8. Click **Next**.
9. Review your changes, and then click **Update**.

Once you assign this label, nothing changes yet. Access will only be affected after you create the policy in the next step to connect the user and resource attributes.

## Step 5: Create the access policy

In this step, you will create the DAG policy to enforce access control (preventing the selected user from seeing the LEO Asset). The policy connects the user attribute and the resource attribute you created earlier.

The active policy will no longer be visible to that user in Sift.

1. In **Access Control**, click **Policies**.
2. Click **Create Policy**.
3. In the **Policy name** box, enter: `fl_deny_leo_asset_access`.
   <Info>
     Replace `fl` in `fl_deny_leo_asset_access` with your initials (first and last name).
   </Info>
4. Select **Deny**.
   * A **Deny** policy sits silently in the background and only triggers when a user matches your specific "denied" criteria. When a match occurs, this policy adds a restriction within their RBAC permissions to block access for that specific resource.
5. Select **All users** (default).
   * **All users** ensures the policy acts as a global guardrail across the entire organization.
6. Select the **Asset** checkbox.
   * This scopes the policy to target only Assets, ensuring efficient evaluation against the `fl_leo_asset` tag you created earlier.
7. Select the **ViewDetails** checkbox.
   * Since your goal is to hide the sensitive LEO data, by denying the **ViewDetails** action, you completely remove the Asset from the user's interface.
   * Because of inheritance, denying **ViewDetails** on the Asset automatically prevents the user from viewing any Channels or Runs inside it.
8. Set conditions. Create the following conditions:

   <MintTable
     columns={["Clause", "Attribute type", "Attribute", "Operator", "Value"]}
     columnWidths={[110, 110, 130, 110, 110]}
     rows={[
     ["`when`", "`user.groupAttributes`", "`fl_leo_denied`", "`=`", "`true`"],
     ["`when`", "`resource`", "`fl_leo_asset`", "`=`", '`"leo"`']
   ]}
   />

   * Once you create the policy, every member of the Group you assigned `fl_leo_denied: true` will no longer be able to see the Asset you tagged with `fl_leo_asset: leo` in Sift.
9. Click **Create**.
10. Review your policy, and then click **Create policy**.

<Accordion title="View Cedar policy">
  You can open a policy and click **View as Cedar policy** to see a human-readable Cedar version.

  [Cedar](https://www.cedarpolicy.com/) is an open source language for defining permissions as policies, and a specification for evaluating those policies. Companies use Cedar to define who is authorized to do what within an application.

  This policy is stored in Sift and editable and verifiable via the API using the Cedar Access Control domain specific language.
</Accordion>

## Conclusion

In this tutorial, you learned how to:

* Use DAG to surgically deny access to a sensitive Asset.
* Create a user attribute to flag restricted users
* Create a resource attribute to identify the target data
* Create a policy to enforce the block.
* By using an explicit deny, you ensured that the restriction overrides any existing permissions, while the inheritance logic automatically protected all data Channels within the Asset.

You can now scale this security model simply by assigning the `fl_leo_denied` attribute to any other Group (or individual user) you need to restrict, without ever needing to modify the policy itself.
