opentdf / platform

OpenTDF Platform monorepo enabling the development and integration of _forever control_ of data into new and existing applications. The concept of forever control stems from an increasingly common concept known as zero trust.
BSD 3-Clause Clear License
17 stars 5 forks source link

Obligations Support #1260

Open strantalis opened 1 month ago

strantalis commented 1 month ago

With the approval of ADR #874. The platform needs to introduce the functionality needed to support obligations. This can be broken down into the following three work areas.

Policy API

In the ADR it was decided to re-use the existing attribute message but add a new field that would distinguish it between a data attribute and an obligation type attribute.

It also requires a new mapping structure to derive resource(tdf policy) attributes -> obligations. The output of this mapping should describe the scope of the obligation. Whether it should apply to a subject or environment entity.

Example Mapping

{cls:topsecret} -> {drm:watermark, scope:environment}

This will require the following

Authorization Service

In the authorization service we need to take the derived obligations and enforce them based on the scope environment or subject .

OTDFCTL Updates

Because we are leveraging attributes in the platform we need to expose obligations in a way that is understandable to the policy administrator. This could either be a flag --category or a new policy sub command otdfctl policy obligation create.

Acceptance Criteria

jakedoublev commented 1 month ago

@strantalis Is this a good place for clarifying questions as I'm working on the CLI command docs in otdfctl? Please let me know if not.

Scenario: I encrypt a TDF with an attribute https://foo.com/attr/test/value/abc an an obligation as https://foo.com/attr/my_obligation/value/do_something. The attribute exists in platform policy but the obligation does not, say because it was deleted by an admin.

Is the expected behavior that the obligation on the TDF (not derived via association to an attribute value within platform policy, but actually added directly on a TDF) must be found in platform policy for access? Or would we expect the entitlement decision alone to be sufficient for access if the obligation doesn't exist in the platform policy? This has ramifications on safe and unsafe create/update behaviors as well as policy import/export since we're supporting both derived obligations via mappings to attributes and adding obligations directly to TDFs.

Note that if the expected behavior is that nonexistent obligations on a TDF will be ignored, and the FQN is the same structure as any other attribute, there's no way to tell from TDF attributes alone that you're considering an obligation and not a regular entitle-able attribute. It would have to have a different FQN structure to be able to be known from the TDF manifest/GetDecisions request as an obligation, like if I added https://foo.com/attr/bar/value/nonsense to a TDF, which would never be accessible if it didn't exist in the platform.

jakedoublev commented 1 month ago

@strantalis Is this a good place for clarifying questions as I'm working on the CLI command docs in otdfctl? Please let me know if not.

Scenario: I encrypt a TDF with an attribute https://foo.com/attr/test/value/abc an an obligation as https://foo.com/attr/my_obligation/value/do_something. The attribute exists in platform policy but the obligation does not, say because it was deleted by an admin.

Is the expected behavior that the obligation on the TDF (not derived via association to an attribute value within platform policy, but actually added directly on a TDF) must be found in platform policy for access? Or would we expect the entitlement decision alone to be sufficient for access if the obligation doesn't exist in the platform policy? This has ramifications on safe and unsafe create/update behaviors as well as policy import/export since we're supporting both derived obligations via mappings to attributes and adding obligations directly to TDFs.

Note that if the expected behavior is that nonexistent obligations on a TDF will be ignored, and the FQN is the same structure as any other attribute, there's no way to tell from TDF attributes alone that you're considering an obligation and not a regular entitle-able attribute. It would have to have a different FQN structure to be able to be known from the TDF manifest/GetDecisions request as an obligation, like if I added https://foo.com/attr/bar/value/nonsense to a TDF, which would never be accessible if it didn't exist in the platform.

In other words, I'm wondering if this CLI documentation statement would be true or need further updates Because obligations are a post-entitlement decision, they are safe to delete. Upon deletion, any derived obligations as a result of mappings to platform policy attribute values will be removed, and any TDFs containing obligations within will remain accessible, just without obligations returned along with an access request to drive PEP behavior.

ttschampel commented 1 month ago

What do you think about the attribute enum having values for data (data attribute), obligation_environment (obligation attribute scoped to environment), obligation_subject (obligation attribute scoped to subjects)?

Then we don't need scope in the derived data policy and allows for an obligation attribute to be added directory to the data policy and have the system understand the enforcement scope

jakedoublev commented 1 month ago

What do you think about the attribute enum having values for data (data attribute), obligation_environment (obligation attribute scoped to environment), obligation_subject (obligation attribute scoped to subjects)?

Then we don't need scope in the derived data policy and allows for an obligation attribute to be added directory to the data policy and have the system understand the enforcement scope

Thanks - that's an interesting idea @ttschampel . I could definitely be missing something, but I am not sure if that gives us the answer around expected access decisions when an obligation is on a TDF as data policy (not derived) and not found (related to In the authorization service we need to take the derived obligations and enforce them based on the scope environment or subject .).

I believe I've heard:

  1. entitlement + yes entity condition satisfaction of derived obligations = permit + obligations
  2. entitlement + no entity condition satisfaction of derived obligations = deny + obligations
  3. entitlement + yes entity condition satisfaction for data policy (on TDF) obligations = permit + obligations
  4. entitlement + no entity condition satisfaction for data policy (on TDF) obligations = deny + obligations

But I'm wondering if we should be expected to support a 5th special case as entitlement + data policy (on TDF) obligations not found in platform = permit + obligations. If obligations on data policy need to be a) known to the platform as obligations and b) ignored in an access decision if found in a TDF but not platform policy, that has follow-on effects for safe/unsafe C~R~UD, auth service, and FQN structure. Keeping it a deny decision would also affect safe/unsafe C~R~UD of obligations, but differently so.

Regarding your enum question, at first impression, it seems like keeping the obligation subject/environment scope tied to the obligation entitlement/satisfaction conditions (and/or + in/not_in/contains) would be preferable for long-term flexibility. As long as the entity type scope is provided along with the fulfillment conditions to the resolution logic run by Auth Service, it'll be available for derived and with-TDF-data obligations alike. However, I don't think we know all the use cases of obligations yet across varied platform consumers and how subject and environment might both be relevant to some obligations.

Derived obligations to data attributes are many : many

Do we know if we have many : one or one : one for obligation entitlement/satisfaction conditions to obligations?

It seems like the immediate use cases for obligations I've heard about so far have usually been environment-scoped as they're environment driven, like how watermark never seems like it would be subject-fulfilled, only by a PEP as environmental entity. I haven't heard about a need for subject entitlement to satisfy obligation entitlements, but could see them useful as a bypassing mechanism in automations or security scan/test jobs.

If only the obligation satisfaction conditions are scoped not the obligations themselves, the auth service condition resolution logic would still have a scope alongside a condition to evaluate, but we wouldn't be closing the door down the road to fulfillment of a single obligation by either an environmental entity condition or a subject entity condition.

ttschampel commented 1 month ago

Sorry, my comments were not directed at your question but was a general comment to where to put scope.

With regard to your question: I think obligations attributes should be treated like data attributes with regard to a platform not having knowledge of an attribute. If a TDF shows up with a data attribute the platform doesn't know about you get a DENY. I think this should be true for obligations as well. In the CLI flow it would be nice to notify a user if they are deleting an attribute / attribute value that is referenced by a derived obligations present could be cascade deleted. I'm also ok with it failing b/c of the FK reference and forcing the user to submit derived obligation mapping delete commands first.

My comment was target at this scenario:

  1. Data producer mints a new TDF and adds a obligation attribute to the policy.
  2. No derived obligations exist in the platform, but the obligation attribute does exist in the system
  3. What should the platform do with this obligation since it does not know how to enforce this obligation with regards to the entity type.

My possible solution: Add those new enums so the platform knows its an obligation and is scoped to a certain entity category. This also removes the need to additionally define the scope in derived obligation mappings