Role-based access control (RBAC)

Every resource in Dyff is “owned” by exactly one Account. Accounts are granted access to Dyff API endpoints via APIKey objects. Access grants can apply to individual entities or to all entities owned by an account. For example, typical user accounts can read and consume all entities owned by the public account.

Individual Dyff API operations are authorized with bearer tokens passed as an HTTP header:

Authorization: Bearer <token>

The token is a JSON Web Token (JWT). A JWT consists of a header and a payload, both JSON objects, encoded as base64 strings. The header+payload string is then signed with a private key. The api-server checks the signature and, if it matches, applies the permissions encoded in the payload. A user can’t grant themselves additional privileges because they don’t have the private key to sign the modified token.

The entire token is a secret. Anyone who has the token can exercise all privileges granted by the token.

  • Tokens MUST NOT be stored anywhere.

  • Tokens MUST NOT be checked in to source control.

  • Operations that transmit and receive tokens MUST use an encrypted channel (i.e., https).

  • The server SHOULD check validity of the signature before making any database queries. Checking the signature is cheap and this reduces exposure to DoS attacks using forged tokens.

RBAC Schemas

The payload information for the token is represented by an APIKey object. Some of the fields correspond to JWT registered claims, such as “Subject” and “Expiration Time”. The main part of the payload consists of a list of AccessGrant objects. For revokable API keys (such as those tied to an Account), there is also an optional secret that allows matching the key to a list of keys in the authorization database.

Note

Access grants are additive.

class dyff.schema.platform.APIKey(*, id: str, subject: str, created: datetime, expires: datetime, secret: str | None = None, grants: list[AccessGrant] = None)

Bases: DyffSchemaBaseModel

A description of a set of permissions granted to a single subject (either an account or a workload).

Dyff API clients authenticate with a token that contains a cryptographically signed APIKey.

field created: datetime [Required]

When the APIKey was created. Maps to JWT ‘iat’ claim.

field expires: datetime [Required]

When the APIKey expires. Maps to JWT ‘exp’ claim.

field grants: list[AccessGrant] [Optional]

AccessGrants associated with the APIKey

field id: str [Required]

Unique ID of the resource. Maps to JWT ‘jti’ claim.

field secret: str | None = None

For account keys: a secret value to check when verifying the APIKey

field subject: str [Required]

Subject of access grants (‘<kind>/<id>’). Maps to JWT ‘sub’ claim.

Access Grants

An AccessGrant grants access to call particular functions on particular instances of particular resource types. Particular instances can be specified either individually by ID, or by the Account that owns them. For example, most accounts will have permission to call the get function on any resource of any type owned by the public account.

class dyff.schema.platform.AccessGrant(*, resources: ConstrainedListValue[Resources], functions: ConstrainedListValue[APIFunctions], accounts: list[str] = None, entities: list[str] = None)

Bases: DyffSchemaBaseModel

Grants access to call particular functions on particular instances of particular resource types.

Access grants are additive; the subject of a set of grants has permission to do something if any part of any of those grants gives the subject that permission.

field accounts: list[str] [Optional]

The access grant applies to all resources owned by the listed accounts

field entities: list[str] [Optional]

The access grant applies to all resources with IDs listed in ‘entities’

field functions: list[APIFunctions] [Required]

List of functions on those resources to which the grant applies

field resources: list[Resources] [Required]

List of resource types to which the grant applies

Resources

This enum defines the canonical names of Dyff resources. We adopted the Kubernetes convention, where the concrete type or “kind” of a resource is a CamelCase class name, but the canonical name is the lower-case plural form. The resource name is used in API endpoint paths (/inferencesessions/create) and for groups of operations in the Python client (client.inferencesessions.create()). These same names are used for the corresponding Kubernetes custom resources, although the actual definitions of the Kubernetes resources in dyff-operator are different from the Python resource definitions in dyff-api.

class dyff.schema.platform.Resources(value)

Bases: str, Enum

The resource names corresponding to entities that have API endpoints.

static for_kind(kind: Entities) Resources
ALL = '*'
Analysis = 'analyses'
Audit = 'audits'
AuditProcedure = 'auditprocedures'
DataSource = 'datasources'
Dataset = 'datasets'
Documentation = 'documentation'
Evaluation = 'evaluations'
Family = 'families'
History = 'histories'
InferenceService = 'inferenceservices'
InferenceSession = 'inferencesessions'
Measurement = 'measurements'
Method = 'methods'
Model = 'models'
Module = 'modules'
Report = 'reports'
Revision = 'revisions'
SafetyCase = 'safetycases'
Task = 'tasks'

Deprecated since version 0.5.0: The Task resource no longer exists, but removing this enum entry breaks existing API keys.

API Functions

This enum defines the “categories” of API operations to which access can be granted. Some functions grant access to multiple endpoints that are all needed to complete a task. For example, uploading a dataset requires access to create, upload, and finalize endpoints for the dataset. Granting the API function create on the datasets resource grants access to all three of these endpoints.

class dyff.schema.platform.APIFunctions(value)

Bases: str, Enum

Categories of API operations to which access can be granted.

all = '*'
consume = 'consume'

Use the resource as a dependency in another workflow.

Example: running an Evaluation on a Dataset requires consume permission for the Dataset.

create = 'create'

Create a new instance of the resource.

For resources that require uploading artifacts (such as Dataset), also grants access to the upload and finalize endpoints.

data = 'data'

Download the raw data associated with the resource.

delete = 'delete'

Set the resource status to Deleted.

download = 'download'

Deprecated since version 0.5.0: This functionality has been consolidated into data.

edit = 'edit'

Edit properties of existing resources.

get = 'get'

Retrieve a single resource instance by ID.

query = 'query'

Query the resource collection.

strata = 'strata'

Deprecated since version 0.5.0: Similar functionality will be added in the future but with a different interface.

terminate = 'terminate'

Set the resource status to Terminated.

upload = 'upload'

Deprecated since version 0.5.0: This functionality has been consolidated into create.

Token Lifetime

Tokens can be either persistent or ephemeral.

Persistent tokens are used for granting access to long-lived subjects such as user Accounts. They have a .secret field that can be compared to a (hashed) secret in the authorization database, and removing the secret from the database effectively revokes access for that token.

Ephemeral tokens are used for inter-service communication and for temporarily authorizing a narrow operation scope for a specific task. For example, we issue ephemeral tokens for inference sessions to allow making inference calls to that specific session.