Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/vale-styles/config/vocabularies/Opentdf/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ Docusaurus
[Oo]tdfctl
API
(?i:tdf)
[Nn]amespace
[Nn]amespac(e[ds]?|ing)
Keycloak
Virtru
SDK
IdP
NPE
PE
FQN
FQNs?
JWT
proto
Postgres
Expand Down Expand Up @@ -38,3 +38,4 @@ enum
OR'd
NPEs
top_secret
AAVs?
4 changes: 2 additions & 2 deletions docs/components/authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ Version 2 of Authorization Service introduced the following changes:
The entity identifier is a request proto object allowing multiple structures representing an entity to stand in as the entity in an Auth Service request:
- an Entity Chain (the response from an `entityresolutionservice.v2.CreateEntityChainsFromTokens` call)
- a Token (access token JWT)
- the FQN of a Registered Resource Value (_EXPERIMENTAL_)
- the FQN of a Registered Resource Value (e.g. `https://example.com/reg_res/network/value/private`, or `https://reg_res/network/value/private` _DEPRECATED_)

#### Resource

The resource is a request proto object allowing multiple structures representing a resource to stand in as the resource in an Auth Service Decision request:
- a list of Attribute Values FQNs
- the FQN of a Registered Resource Value (_EXPERIMENTAL_)
- the FQN of a Registered Resource Value (e.g. `https://example.com/reg_res/s3_bucket/value/bucket1`, or `https://reg_res/s3_bucket/value/bucket1` _DEPRECATED_)

### GetEntitlements

Expand Down
4 changes: 2 additions & 2 deletions docs/components/policy/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Definition_B-->Value_D;

## Namespaces

A Namespace is the parent container for a set of attributes. Consider the following example:
A Namespace is the parent container for a set of attributes. It can also optionally contain [registered resources](./registered_resources). Consider the following example:

Alice wants to control access in a platform instance based on Attribute Values of the Definitions `color` and `order`. She creates attribute definitions for each and assigns values to them.

Expand Down Expand Up @@ -78,7 +78,7 @@ Unsafe actions on policy attributes include:
- **Namespaces**:
- Updating the namespace name (e.g., `demo.com` to `example.org`).
- Reactivation (does not cascade to reactivate attributes and their values).
- Deletion (permanently removes the namespace and all associated attributes and values).
- Deletion (permanently removes the namespace and all associated attributes, values, and registered resources).
- **Attribute Definitions**:
- Updating the attribute definition name.
- Changing the order of attribute values.
Expand Down
2 changes: 1 addition & 1 deletion docs/components/policy/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ Components of Policy include:
- Actions
- Subject Mappings
- Subject Condition Sets
- Registered Resources
- Registered Resources (scoped to Namespaces)
- Resource Mappings
- Key Access Grants (KAS Grants)
92 changes: 82 additions & 10 deletions docs/components/policy/registered_resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,32 @@

A Registered Resource consists of:

1. A `Registered Resource`
2. A `Registered Resource Value`
3. One or more `Action Attribute Values`
1. An optional `Namespace` (the same organizational container used by [attributes](./attributes))
2. A `Registered Resource`
3. A `Registered Resource Value`
4. One or more `Action Attribute Values`

A Registered Resource has a unique name and may contain multiple, unique Registered Resource Values.
A Registered Resource may optionally belong to a Namespace. It has a unique name and may contain multiple, unique Registered Resource Values.

A Registered Resource Value is used to represent a specific instance of the Registered Resource and can be referenced by a FQN (Fully Qualified Name) in the form of `https://reg_res/<registered_resource.name>/value/<registered_resource_value.value>`.
A Registered Resource Value is used to represent a specific instance of the Registered Resource and can be referenced by a FQN (Fully Qualified Name).

When a Registered Resource is associated with a namespace, the FQN takes the form `https://<namespace>/reg_res/<registered_resource.name>/value/<registered_resource_value.value>`.

:::warning Deprecation
Non-namespaced Registered Resources are deprecated. Their FQNs use the form `https://reg_res/<registered_resource.name>/value/<registered_resource_value.value>`. A future version will require all Registered Resources to be associated with a namespace. Use the `otdfctl migrate registered-resources` command to migrate existing non-namespaced Registered Resources.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are they deprecated? Or do we just recommend that you don't create non-namespaced RRs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were deprecating non namespaced policy (like why we originally made namespaces required for some policy objects). My understanding was that due to breaking changes we were making namespaces optional to give consumers a grace period and avoid breaking changes. I may have understood incorrectly, or my understanding may be outdated? I'll reach out to the team for clarification.

:::

:::tip
Registered Resource Values are not namespaced, so their FQNs cannot contain one. To address this, a prefix of `https://reg_res/` has been chosen to identify a FQN as a Registered Resource Value.
Registered Resource Value FQNs contain the `reg_res` path segment to distinguish them from attribute FQNs under the same namespace.
:::

Registered Resource Values may contain multiple Action Attribute Values, which are unique mappings of an action to an attribute value. These mappings are used in Policy Decision Points for access control decisions.

```mermaid
graph LR;

Namespace-.->|optional|Registered_Resource;

Registered_Resource-->Registered_Resource_Value_A;
Registered_Resource-->Registered_Resource_Value_B;

Expand All @@ -43,16 +52,79 @@ Action_Attribute_Value_D-->Attribute_Value_D;

```

## Namespacing

Registered Resources can optionally be associated with a namespace by providing a `namespace_id` or `namespace_fqn` when creating the resource. Non-namespaced Registered Resources are deprecated and a future version will require all Registered Resources to have a namespace.

### Uniqueness

Namespaced Registered Resource names are unique within their namespace. Non-namespaced Registered Resource names are globally unique. The same name can exist as both a namespaced and a non-namespaced resource.

### Name Lookup

When getting a Registered Resource by name without specifying a namespace, and both a namespaced and non-namespaced resource share that name, the non-namespaced one is returned. To retrieve the namespaced one, provide the `namespace_id` or `namespace_fqn` in the request.

### Namespace Deletion Cascade

Deleting a namespace cascades to delete all Registered Resources (and their values) within that namespace.

### `NamespacedPolicy` Enforcement

The platform supports a `NamespacedPolicy` server configuration flag. When enabled, all new Registered Resources are required to have a namespace. This flag will become the default in a future version.

# Examples

## As a Resource

Alice is a cloud security architect. She needs to control user access to S3 buckets in her cloud environment. She defines a Registered Resource called `s3_bucket` with values like `bucket1`, `bucket2`, and `bucket3`. For the Registered Resource Value `https://reg_res/s3_bucket/value/bucket1`, she might define Action Attribute Values for actions such as `read`, `create`, and `delete` on attribute values such as `https://demo.com/attr/classification/value/topsecret`, `https://demo.com/attr/classification/value/secret`, and `https://demo.com/attr/classification/value/unclassified` to enforce the desired access control.
Alice is a cloud security architect. She needs to control user access to S3 buckets in her cloud environment. She defines a Registered Resource called `s3_bucket` under the `demo.com` namespace, with values like `bucket1`, `bucket2`, and `bucket3`. For the Registered Resource Value `https://demo.com/reg_res/s3_bucket/value/bucket1`, she might define Action Attribute Values for actions such as `read`, `create`, and `delete` on attribute values such as `https://demo.com/attr/classification/value/topsecret`, `https://demo.com/attr/classification/value/secret`, and `https://demo.com/attr/classification/value/unclassified` to enforce the desired access control.

In this case, Policy Decision Points would evaluate a user's attributes and subject mappings (acting as the entity) against the Action Attribute Values of the `https://reg_res/s3_bucket/value/bucket1` Registered Resource Value (acting as the resource).
In this case, Policy Decision Points would evaluate a user's attributes and subject mappings (acting as the entity) against the Action Attribute Values of the `https://demo.com/reg_res/s3_bucket/value/bucket1` Registered Resource Value (acting as the resource).

## As an Entity

Bob is a network security administrator in a large organization. He needs to manage data communications across various networks that have different classification-based access controls. He defines a Registered Resource called `network` with values like `private` and `public`. For the Registered Resource Value `https://reg_res/network/value/private`, he might define Action Attribute Values for actions such as `read` and `create` on attribute values such as `https://demo.com/attr/classification/value/topsecret` and `https://demo.com/attr/classification/value/secret`.
Bob is a network security administrator in a large organization. He needs to manage data communications across various networks that have different classification-based access controls. He defines a Registered Resource called `network` under the `demo.com` namespace, with values like `private` and `public`. For the Registered Resource Value `https://demo.com/reg_res/network/value/private`, he might define Action Attribute Values for actions such as `read` and `create` on attribute values such as `https://demo.com/attr/classification/value/topsecret` and `https://demo.com/attr/classification/value/secret`.

In this case, Policy Decision Points would evaluate the Action Attribute Values of the `https://demo.com/reg_res/network/value/private` Registered Resource Value (acting as the entity) against either the Action Attribute Values of the `https://demo.com/reg_res/network/value/public` Registered Resource Value or against a TDF's attributes (acting as the resource).

# Migrating Non-Namespaced Registered Resources

The `otdfctl migrate registered-resources` command migrates legacy non-namespaced Registered Resources to namespaced ones.

:::caution
Migration creates a new namespaced resource, recreates its values with their action-attribute-value mappings, then deletes the old non-namespaced resource. The migrated resource will have a new UUID. Back up your data before running with `--commit`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are changing this to not delete the old, but add a metadata tag that we can then use with a prune or cleanup command.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, what would you recommend? I'm thinking I can keep this block as current behavior but mention future expected behavior. Alternatively, I can just remove mention of migration until we get to an expected state.

:::

## Modes

### Dry Run (default)

Running without flags previews resources that need migration and their auto-detected namespaces. No changes are made.

```bash
otdfctl migrate registered-resources
```

### Batch

The `--commit` flag migrates all resources at once. The tool auto-detects namespaces from action attribute values where possible and prompts for a batch namespace for any resources where the namespace cannot be determined.

```bash
otdfctl migrate registered-resources --commit
```

### Interactive

The `--interactive --commit` flags walk through each resource one-by-one, allowing per-resource namespace selection with options to skip individual resources or abort the migration.

```bash
otdfctl migrate registered-resources --interactive --commit
```

## Namespace Auto-Detection

The migration tool inspects each resource's action attribute values to determine the target namespace:

In this case, Policy Decision Points would evaluate the Action Attribute Values of the `https://reg_res/network/value/private` Registered Resource Value (acting as the entity) against either the Action Attribute Values of the `https://reg_res/network/value/public` Registered Resource Value or against a TDF's attributes (acting as the resource).
- **Deterministic**: All action attribute values reference the same namespace — that namespace is used automatically.
- **Conflicting**: Action attribute values reference multiple namespaces — manual selection is required.
- **Undetermined**: Action attribute values exist but namespace data is unavailable — manual selection is required.
- **No AAVs**: The resource has no action attribute values — manual selection is required.
2 changes: 1 addition & 1 deletion docs/sdks/policy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Policy in OpenTDF is the set of rules that govern who can access data and under

## Namespaces

A **namespace** is the top-level organizational unit for attributes. Attribute FQNs are scoped to a namespace URI (e.g., `https://example.com`).
A **namespace** is the top-level organizational unit for attributes and optionally for [registered resources](/components/policy/registered_resources). FQNs are scoped to a namespace URI (e.g., `https://example.com`).

:::note Soft-delete only
Namespaces are deactivated, not permanently deleted. There is no hard-delete operation and no restore operation exposed via the SDK.
Expand Down
Loading