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 aDataset
requiresconsume
permission for theDataset
.
- create = 'create'
Create a new instance of the resource.
For resources that require uploading artifacts (such as
Dataset
), also grants access to theupload
andfinalize
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.