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
15 stars 4 forks source link

new capability to set a platform `mode` #1033

Open strantalis opened 3 days ago

strantalis commented 3 days ago

Currently, when running the platform, we need to explicitly set whether a service is enabled. This works, but as we start to look at running a service like KAS independently, we need to consider how to manage this configuration more efficiently. It will become cumbersome if every service within the platform needs to be individually enabled or disabled.

Additionally, not every service requires the same tooling. For example, KAS does not need opa, yet opa is created regardless of the platform configuration.

https://github.com/opentdf/platform/blob/c3828d088a3483b78079cd257b4237291cf7b6f0/service/pkg/server/start.go#L64-L69

First, we need to define what constitutes the core platform.

Core Platform:

The two other services that aren't part of the core are:

Authorization Service
Key Access Service (KAS)

If we agree that these are the main services, we can define the following modes:

As users potentially need to extend or build on top of OpenTDF they could also potentially need to define their own modes as well. This gives us the ability to provide that. So as they add new services under services that will essentially become a mode.

Current configuration looks something like this where each service is explicitly defined under the services block.

https://github.com/opentdf/platform/blob/c3828d088a3483b78079cd257b4237291cf7b6f0/opentdf-dev.yaml#L11-L39

In the new approach, the enabled field would be removed as everything would be driven by the mode.

https://github.com/opentdf/platform/blob/main/service/pkg/serviceregistry/serviceregistry.go#L22

We wouldn't be required to set defaults for those services like we do today.

https://github.com/opentdf/platform/blob/main/service/internal/config/config.go#L27

Example All Mode

mode: all
credentials:
  client_id: xxxxxx
  client_secret: xxxxx
db:
  <db config>
services:
  kas:
   <any kas config>
  core:
    <any core config>
  authorization:
    <an authorization config>

Example Core Mode

mode: core # Not sure if we want to call this mode something else?
credentials:
  client_id: xxxxxx
  client_secret: xxxxx
db:
  <db config>
services:
  core:
    <any core config >

Example KAS Mode

mode: kas
credentials:
  client_id: xxxxxx
  client_secret: xxxxx
remote_services:
  core: https://core.opentdf.io:9000
services:
  kas:
    <any core config>

As an alternative to having a root-level remote_services block, we could also consider the following configuration, although it might be more confusing:

mode: kas
credentials:
  client_id: xxxxxx
  client_secret: xxxxx
services:
  kas:
    core_endpoint: https://core.opentdf.io:9000
    <any core config>
jakedoublev commented 3 days ago

This looks wise. I have a couple questions:

  1. Is credentials a new addition, or a relocation of the auth service client id and secret config? https://github.com/opentdf/platform/blob/c3828d088a3483b78079cd257b4237291cf7b6f0/opentdf-dev.yaml#L30-L31

  2. Should we make modes extendable for downstream PEPs?

If the platform has a new service added to its core (i.e. new-core-service), as a downstream PEP developer my core mode could extend via hook into whatever services the platform considers core rather than duplicating policy, well-known, new-core-service, my-core-pep-service. It seems like there'd be fewer configuration changes needed when upgrading.

strantalis commented 3 days ago
  1. Is credentials a new addition, or a relocation of the auth service client id and secret config? https://github.com/opentdf/platform/blob/c3828d088a3483b78079cd257b4237291cf7b6f0/opentdf-dev.yaml#L30-L31

Yeah, I kind of snuck it in there. Right now, each service has its own credentials config. But when we're running everything together, it doesn’t really make sense for each service to have its own separate credentials. Plus, using client credentials from the IDP means we’d need to create at least three new clients right now.

By defining a global credentials block, we can use it across the board, whether we're in mode all or running a service on its own.

strantalis commented 3 days ago
  1. Should we make modes extendable for downstream PEPs?

If the platform has a new service added to its core (i.e. new-core-service), as a downstream PEP developer my core mode could extend via hook into whatever services the platform considers core rather than duplicating policy, well-known, new-core-service, my-core-pep-service. It seems like there'd be fewer configuration changes needed when upgrading.

I think they will be extensible if we keep Services as a map.

https://github.com/opentdf/platform/blob/c3828d088a3483b78079cd257b4237291cf7b6f0/service/internal/config/config.go#L27

Each key in the map could be considered a mode is how I was thinking about it.

I think we probably need to try and implement this to really shake the config proposal changes out.

jrschumacher commented 3 days ago

In my mind the core is the service which you reach out to for networking info. So if a PEP is running in the core that is fine but it will just use the SDK to reach out to the other systems and the platform will negotiate that based on the remotes.

If you run the PEP in a microservice it will require knowledge of the core, but that's it. Might be a bit costly to call the core to then be directed to a remote KAS but that's fine for now. Less complexity than having to manage all the URLs of every microservice deployment.

strantalis commented 3 days ago

In my mind the core is the service which you reach out to for networking info. So if a PEP is running in the core that is fine but it will just use the SDK to reach out to the other systems and the platform will negotiate that based on the remotes.

If you run the PEP in a microservice it will require knowledge of the core, but that's it. Might be a bit costly to call the core to then be directed to a remote KAS but that's fine for now. Less complexity than having to manage all the URLs of every microservice deployment.

I don’t think it will be expensive. We already call the platform when creating a new client to get IDP information, and there are always optimizations we can implement in the future.

The only other static endpoint, in my mind, would be the authorization service. KAS endpoints will be more dynamic, driven by core policy, so clients will have to reach out to get a full attribute value definition.

@jrschumacher Are you suggesting we create a root-level config for core_endpoint or platform_endpoint?