# Object and property security policies Object security policies allow you to configure view permissions on an object instance by configuring security policies on the object type, independently of the permissions on the backing data source. These are used to achieve *row-level security*. The visibility of specific properties can be guarded using additional *property security policies*. These are identical to object security policies, except they only apply to a selection of properties. These are used to achieve *column-level security*. By default, object security policies are applied to all properties. When a property security policy includes a property, the user must pass both the object security policy and the property security policy to view the property value. The combination of object and property security policies is used to achieve *cell-level security*. If a user does not pass the object security policy, the object instance will not be viewable to that user. If they pass the object security policy but do not pass the property security policy, they will see a *null* value in place of the property value. :::callout{theme="warning" title="Read-time enforcement only"} Object and property security policies filter what a user can read. Users can never read object instances or property values they are not authorized to see. These controls do not extend to downstream outputs or exports. To keep data protected as it flows downstream, pair these controls with a [marking](../../security/markings/index.md) or [Classification-based Access Control](../../security/classification-based-access-controls/index.md). For the full model, see [Access control propagation](../../security/access-control-propagation/index.md). ::: ## Configure object and property security policies Access to an object instance and its properties is determined by the following conditions: * `Viewer` access to the object type. * Passing a granular policy, if configured. * Passing any [marking](../../security/markings/index.md), [organization](../../security/orgs-and-spaces/index.md#organizations), or [classification](../../security/classification-based-access-controls/index.md) checks. When an object or property security policy is configured, users do not need `Viewer` permissions to the object type's backing data sources to view object instances. :::callout{theme="warning"} If your enrollment uses the legacy [datasource-derived permissions model](../ontology-permissions-legacy/index.md#datasource-derived-permissions), users still require `Viewer` permissions on the backing data source to view the object type and its instances. This requirement applies even when an object security policy is configured. Because datasource-derived permissions defeat the decoupling that object security policies provide, we recommend [migrating to project-based permissions](../ontology-permissions/index.md) before configuring object security policies. ::: Download permissions are evaluated separately from the view permissions described above. When an object type is secured with a security policy, the location of the object type determines whether the platform checks download permissions on the object type or on the backing data source, as described in [permissions to download object data](#permissions-to-download-object-data). Consider an example where a `Passenger` object type has the properties `User ID`, `Flight Number`, `Seat Assignment`, `Name`, `Address`, and `Phone Number`. Some passengers are VIPs, whose information can only be seen by users who have access to a `VIP` marking. Additionally, some properties, such as `Name`, `Address`, and `Phone Number`, should be visible only to users who have the `PII` marking, and are authorized to view personally identifiable information. Since the backing dataset consists of sensitive data, it should be marked with `PII` and `VIP`. However, users without sensitive markings should still be able to access a passenger’s flight details. The following steps can be taken to secure the `Passenger` object type using object security policies. 1. Navigate to the **Security** tab of the object type.

The 'Security' tab for an object type in Ontology Manager.

2. Select **Create** under the **Security policies** section to override data source policies with object security policies.

![The "Create" option under the "Security policies" section.](../../../assets/2d98f4f7e2af23453793115ba80e69897e1ffb38317e645bddf42b4f71243661.webp)

3. Create the object security policy that edits view permissions for object instances. You have the option to add a granular policy and edit the organization and markings.

![The object security policy overview.](../../../assets/4d0edba6a535aeee5504b10e41d87f5aa01565f0440569feaad2f5a567b15ffd.webp)

4. In the **Markings** configuration, stop inheriting the `PII` and `VIP` markings so that users without those markings can see object instances.

![Markings listed under access requirements with the option to start and stop inheriting markings.](../../../assets/ea55ea5fb615865acb66a288b29bf6c397427c8bee87b544c1c71d5c0edc0632.webp)

5. Add a **Granular policy** to limit access to VIPs. The `VIP` marking is added as a [mandatory control property](../../object-link-types/mandatory-control-properties/index.md). Every row has a set of markings in the mandatory control property that need to be satisfied by a user to access that object instance.

![The "Compose granular policy" view, with the option to add a condition on the VIP mandatory control property.](../../../assets/5f105ee98285af1e3c03d6bc3641c68216aa48a94d2c6c3719401bd98381f0b4.webp)

:::callout{theme="danger"} Avoid using `NOT` conditions with group, marking, or organization memberships. Using a `NOT` condition in these circumstances is a misconfiguration. The platform supports scoped tokens, which carry only a subset of a user's permissions. These tokens may lack the attribute the `NOT` condition checks against, causing the condition to pass and grant more access than intended. ::: 6. This creates the object security policy. Now, we need to secure the `PII` properties with the `PII` marking. We can do this by adding a property security policy.

![The option to add a property security policy in the "Security policies" section.](../../../assets/0e248c66c2aeae74ea533c5fd2f376635ae0b076aeac26b7290ca1dd01955192.webp)

7. Select the properties that need to be secured and give the policy a name. Then, add the `PII` marking in the **Manage markings** setting. The configuration settings for property security policies are identical to object security policies.

![The property security policy overview with the policy name and properties.](../../../assets/25a82532823287fc3aff44aabcec8a21441f18ae8c0b12aef7520947453aff08.webp)

Select **Manage markings** for the property security policy and add the `PII` marking.

![The "Access requirements" section listing inherited markings.](../../../assets/fa54dedcc9c3d1f585e62acd8818fd92bb966c0f39101cf01c2bddfcfe012833.webp)

8. This will create the property security policy. The properties included in the policy are now secured by the object security policy and the new property security policy. Properties not included in any property security policy will still be secured by the object security policy.

![The properties covered by the object security policy.](../../../assets/e8a5b6132c22d716473887489ab960c6ea2ff9a008ff1b342a440c6ac7e1cda3.webp)

![The properties covered by the property security policy.](../../../assets/2a08d001d6de64fb01cc3a2fbfe85238dfd6106c4f761b84aa1bda5e9d7ad2e3.webp) ### Permissions to edit security policies To create or edit an object or property security policy, you must be an **Owner** of the object type. If your enrollment uses [project-based permissions](../ontology-permissions/index.md), this means you must hold the `Owner` role on the project that contains the object type. If your enrollment uses the legacy [datasource-derived permissions model](../ontology-permissions-legacy/index.md#datasource-derived-permissions), this means you must be an `Owner` on the Ontology. Once security policies are configured on an object type, adding or removing properties also requires `Owner` on the Ontology. This makes many common workflows highly restrictive, and is a further reason we recommend [migrating to project-based permissions](../ontology-permissions/index.md) before configuring object security policies. ### Permissions to download object data When an object type is secured with an object or property security policy, the location of the object type determines where the platform checks download permissions: * **Object types saved in a [project](../ontology-permissions/index.md):** The platform checks download permissions on the object type. * **Object types using [ontology roles](../ontology-permissions-legacy/index.md#ontology-roles) or [datasource-derived permissions](../ontology-permissions-legacy/index.md#datasource-derived-permissions):** The platform checks download permissions on the backing data source. ### Property security policy restrictions The following restrictions apply when configuring one or more property security policies: * An object security policy must already be configured. * The primary key property cannot be a member of any property security policy. * A non-primary key property can be a member of at most one property security policy. ## Configure access to object types Access to object types can be configured in the [ontology metadata permissions](../ontology-permissions/index.md). The user needs to be able to [view the object type definition and instances](../ontology-permissions/index.md#viewing-object-types-and-objects). ## Configure a granular policy [Learn more about configuring granular policies for row-level security](../../platform-security-management/manage-granular-policies/index.md). ### Granular policy limits for property security policies The granular policy comparison limit of 10,000 applies separately to the object security policy and to each combination of the object security policy with a single property security policy. For each property security policy, add its granular policy's [comparison weight](../../platform-security-management/manage-granular-policies/index.md#policy-limitations) to the object security policy's granular policy weight. This combined weight must stay under 10,000. For example, in the `Passenger` object type, keep the object security policy that controls access to VIP passengers and configure two property security policies: `Flight details` and `Contact details`. In this example, flight details are now also restricted to authorized airline staff. Keep the `PII` marking on `Contact details` to protect `Name`, `Address`, and `Phone Number`. Suppose you also configure granular conditions on each property security policy, with the following comparison weights: | Security policy | Properties | Granular policy weight | Weight checked against the 10,000 limit | | --- | --- | --- | --- | | Object security policy | `User ID` (primary key); also applies to all other properties | 3,000 | 3,000 | | `Flight details` property security policy | `Flight Number`, `Seat Assignment` | 5,000 | 3,000 + 5,000 = 8,000 | | `Contact details` property security policy | `Name`, `Address`, `Phone Number` | 6,000 | 3,000 + 6,000 = 9,000 | Each property security policy combines only with the object security policy, giving a combined weight of 8,000 for `Flight details` and 9,000 for `Contact details`. The `Flight details` policy's weight does not contribute to the `Contact details` policy's combined weight, or vice versa. The object security policy still applies to every property, including properties covered by a property security policy. You do not need to repeat its granular conditions in each property security policy. ## Configure mandatory controls By default, an object security policy will inherit all mandatory controls from its data sources. These include [markings](../../security/markings/index.md), [organizations](../../security/orgs-and-spaces/index.md#organizations), and [classifications](../../security/classification-based-access-controls/index.md). The object security policy can then be further customized to add new mandatory controls and remove inherited mandatory controls that are no longer necessary. ## Materializations with object security policies Object security policies also determine the permissions for viewing [materialized](../../object-edits/materializations/index.md) data in the object type. Currently, object types with object security policies can only be materialized to Foundry datasets. The most restrictive permissions are applied to materialized data. This includes the following: * All markings from the backing data sources. * Additional markings applied on object or property security policies. * Markings from all mandatory control properties used in the granular policies of all object and property security policies. :::callout{theme="warning"} Transactions on materialized datasets are secured by the security policies generated at the time of the materialized dataset build. When users add or remove a marking in their object or property security policies, the marking will only be reflected in the transactions committed at the time that the marking is present. Transactions are committed when the materialization is [scheduled to build](../../object-edits/materializations/index.md#build-schedules-in-writeback-and-materialized-datasets), which is configured by the user. After adding a marking to an object or property security policy, make sure to do the following: * Build the materialization dataset if the markings need to propagate to the materialization dataset immediately. * Mark the materialization or backing dataset with the marking to secure all historical transactions on the materialization dataset. ::: ## Test object security policies When configuring object security policies, you can test a specific user's ability to view the properties of an indexed object type based on your unsaved object security policy. You can also edit the values of properties referenced in granular policies to test hypothetical object instances and determine if your policy is correctly configured. Select **Test policies** from the **Security policies** section to launch the **Test security policies** modal. ![Entry point to test object security policies.](../../../assets/ded210c5bd87a9bfe61fac42f184e8ca2ca5da7641aa5f31e4807e11ce0bcd84.webp) In the **Test security policies** modal, use the **Configure test** panel to select a **User** whose visibility access you wish to test on a given **Object**. The **Results** section indicates which properties on the object the user can view based on the current security policy configuration. ![The security policy testing dialog, where you can test a user's visibility and edit property values for hypothetical object instances.](../../../assets/ac5a462603183ed6a625690a8febb4f318fea0fd88c52c304b26fc752c1806a2.webp) ### Current object security policy testing limitations * You cannot test [derived property](../../ontology/derived-properties/index.md) visibility, as this also relies on the user's visibility on the derived property's source object. * If you are neither a member nor administrator of an organization that is referenced in the security policy, then guest memberships and secondary organizations will not be taken into account during testing. Foundry indicates this by displaying a warning callout that enumerates the organizations you do not have permissions on. ## Migrate from restricted views to object security policies Object security policies are recommended over [restricted views](../../security/restricted-views/index.md) for most use cases built on the Ontology. They provide unified cell-level security, near-instantaneous policy updates, and support for streaming and branching. [Learn more about the benefits of object and property security policies.](../managing-object-security/index.md#benefits-of-object-and-property-security-policies) If you previously set up object types backed by restricted views and want to migrate to object security policies, you can use the migration tool described below. [Learn more about object and property policies versus data source policies.](../managing-object-security/index.md#object-and-property-policies-vs-data-source-policies) You can migrate an object type's data source from a restricted view to the backing dataset of the restricted view, secured by object security policies, using the migration tool in the **Security** tab. The tool configures security policies to match the policies defined on the restricted view. ![The entry point for migrating from restricted views to object security policies in the Security tab.](../../../assets/eaa702a5a8a051d5466e215dd1a07dcd7cf8e8995ee829ed1ed15fab0e9fbb7c.webp) ### Limitations The migration tool does not support the following restricted view configurations: * Object types with multiple data sources (MDOs). * Object types with multiple materializations or a single restricted view materialization. * Restricted views with [granular policies](../../platform-security-management/manage-granular-policies/index.md) that use unsupported comparison operators, including greater than, greater than or equal, less than, and less than or equal. * Restricted views with granular policies that reference numeric constant values, such as integer, long, or double. * Restricted views with granular policies that reference authorized group IDs, organization marking IDs, or static marking IDs as user properties. Consider using a [mandatory control property](../../object-link-types/mandatory-control-properties/index.md) to achieve equivalent security. ### Preserve discretionary security To preserve project viewing constraints on the data (security configurations inherited from the project the restricted view is in), you can move the object type into the same project as the restricted view using the migration tool. ![The restricted view to object security policy migration tool.](../../../assets/e4bb46d6c0e00dcc9e8a8c6c02d6e7ef7c61dab5b538869b9330e3ad9a537bc3.webp)