From e225ac80376902c41214124057d386e147a88273 Mon Sep 17 00:00:00 2001 From: Ben Leggett <854255+bleggett@users.noreply.github.com> Date: Wed, 13 Apr 2022 13:22:31 -0400 Subject: [PATCH] Sync this repo against https://github.com/virtru/tdf-spec/commit/aaeb3f977839eb821bfcc0e40f626a3c3bf2d33f (#3) - Made minor edits to switch the OpenTDF nonclamenture where appropriate --- .github/PULL_REQUEST_TEMPLATE.md | 15 +-- AttributeObject.md | 47 -------- CONTRIBUTING.md | 13 ++- ClaimsObject.md | 58 ---------- HtmlProtocolExample.html | 188 ------------------------------- KeyAccessObject.md | 39 ------- PolicyObject.md | 39 ------- api/kas-api.yaml | 4 +- manifest-json.md | 163 --------------------------- protocol/README.md | 49 ++++++-- schema/AttributeObject.md | 37 +++--- schema/ClaimsObject.md | 78 +++++++++---- schema/EntitlementObject.md | 35 ++++++ schema/KeyAccessObject.md | 4 +- schema/PolicyObject.md | 2 +- schema/README.md | 12 +- schema/manifest-json.md | 4 +- schema/test/README.md | 3 + 18 files changed, 182 insertions(+), 608 deletions(-) delete mode 100644 AttributeObject.md delete mode 100755 ClaimsObject.md delete mode 100644 HtmlProtocolExample.html delete mode 100755 KeyAccessObject.md delete mode 100755 PolicyObject.md delete mode 100755 manifest-json.md create mode 100644 schema/EntitlementObject.md create mode 100644 schema/test/README.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 871760e..19a841f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,12 +5,13 @@ ### Checklist - [ ] A clear description of the change has been included in this PR. -- [ ] Spec Semver version has been updated in the VERSION file -- [ ] Tagged this branch with new semver version and an annotation describing the change (ex: `git tag -s 4.1.0 -m "Spec version 4.1.0 - did a thing"`) +- [ ] A clear description of whether this change is a _Major_, _Minor_, _Patch_ or _cosmetic_ change as per the [Versioning Guidelines](../CONTRIBUTING.md#version-changes) has been included in this PR. - [ ] All schema validation tests have been updated appropriately and are passing. -- [ ] Version numbers have been updated as per the [Versioning Guidelines](../CONTRIBUTING.md#verison-changes). -- [ ] Major/minor version changes only: A writeup has been included discussing the motivation and impact of this change. -- [ ] Major/minor version changes only: The minimum wait time has elapsed. -- [ ] Project version changes only: I have updated both the `VERSION` file and the `git tag`. +- [ ] MAJOR/MINOR VERSION CHANGES ONLY: This PR should be made in branches prefixed with `draft-` +- [ ] MAJOR/MINOR VERSION CHANGES ONLY: A link to a reference implementation (PR or set of PRs) of the change has been included in this PR. +- [ ] MAJOR/MINOR VERSION CHANGES ONLY: A writeup has been included discussing the motivation and impact of this change. +- [ ] MAJOR/MINOR VERSION CHANGES ONLY: The minimum wait time has elapsed. +- [ ] DRAFT MERGE ONLY: Draft Semver has been updated in the VERSION file (optional) +- [ ] DRAFT MERGE ONLY: Tagged this branch with new semver version and an annotation describing the change (ex: `git tag -s 4.1.0 -m "Spec version 4.1.0 - did a thing"`) +- [ ] DRAFT MERGE ONLY: Version numbers have been updated as per the [Versioning Guidelines](../CONTRIBUTING.md#version-changes). - [ ] This change otherwise adheres to the project [Contribution Guidelines](../CONTRIBUTING.md). -- [ ] Every item in this checklist has been completed. diff --git a/AttributeObject.md b/AttributeObject.md deleted file mode 100644 index b4443d4..0000000 --- a/AttributeObject.md +++ /dev/null @@ -1,47 +0,0 @@ -# Attribute Object - -## Summary -An Attribute Object contains attribute information the TDF3 system uses to enforce attribute-based access control (ABAC). Attributes are used in both the [PolicyObject](PolicyObject.md) to define the attributes that a subject "needs" to gain access in an ABAC sense, and in the [ClaimsObject](ClaimsObject.md) to assert the attributes that an actor "has". -Access decisions are made by comparing the attributes a subject has with the attributes a policy requires. - -Attributes that a subject (or actor, or entity) "has" are referred to as "subject attributes". - -Attributes that subjects "need" in order to access data are referred to as "object attributes". - -The _attribute_ field must be both unique and immutable as it is the reference id for the attribute. All of the other fields are mutable. The attribute string contains three pieces of information - the authority namespace, the attribute name, and the attribute value. - -When encrypting, the client determines which attributes a subject must have in order to decrypt the payload and applies those attributes to the file's [Policy Object](PolicyObject.md). - -When a decrypt is requested, the KAS checks the [Policy Object](PolicyObject.md) against the [Claims Object](ClaimsObject.md) from the requesting client to -ensure the attributes that an entity "has" satisfies those that an entity "needs". - -If this check succeeds, the KAS permits a decrypt operation and returns a valid key which the client can decrypt and use to expose the file contents. - -The public key is used to wrap the object key or key splits on TDF3 file creation. On decrypt, the kasUrl defines where this key or key split can be rewrapped. - -The AttributeObject alone does not define how the KAS will compare a subject attribute to an object attribute when making an access decision. -The KAS uses the namespaced object attributes in the [PolicyObject](PolicyObject.md) look up attribute policies from the cognizant authority -to make its policy decisions. Clients writing policies should use best available information from their organizations to select which AttributeObjects to include to protect the policy. - -## Example - -```javascript -{ - "attribute": "https://example.com/attr/classification/value/topsecret", - "isDefault": true, - "displayName": "classification", - "pubKey": "pem encoded public key of the attribute", - "kasUrl": "https://kas.example.com/", - "tdfVersion:": "x.y.z" -} -``` - -|Parameter|Type|Description|Required?| -|---|---|---|---| -|`attribute`|String|Also known as the "attribute url." The unique resource name for the attribute represented as a case-insensitive URL string. This field must be both unique and immutable as it is the reference id for the attribute. The attribute URL string contains three pieces of information - in the above example, the authority namespace (https://example.com), the attribute name (classification), and the attribute value (topsecret). |Yes| -|`isDefault`|Boolean|If "true" this flag identifies the attribute as the default attribute. If missing (preferred) or false then the attribute is not the default attribute.|No| -|`displayName`|String|A human-readable nickname for the attribute for convenience.|Yes| -|`pubKey`|PEM|PEM encoded public key for this attribute. Often other attributes will use the same pubKey.|Yes| -|`kasUrl`|URL|Base URL of a KAS that can make access control decisions for this attribute.|Yes| -|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 714bab8..165673e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,22 +1,25 @@ # Contribution guidelines -Contributions to the TDF3 specification are welcome! Please be sure to follow these guidelines when proposing changes or submitting feedback. +Contributions to the TDF specification are welcome! Please be sure to follow these guidelines when proposing changes or submitting feedback. ## Proposing Changes -All changes must be proposed using a pull request against this repo. See the GitHub [howto](https://help.github.com/en/articles/about-pull-requests) for more information about publishing a PR from a fork. The PR template checklist must be satisfied before review can take place (with the exception of blocking items like wait time). +1. Pull Requests(PRs) proposing changes should be made in branches prefixed with `draft-` +2. If the changes proposed to the spec would result in a _Major_ or _Minor_ semver version bump (see [versioning guidelines](#version-changes)) to the spec, the spec change MUST LINK TO A REFERENCE IMPLEMENTATION OF THE CHANGES in a publicly-visible Git repository. + - It is suggested that the PR include a link to one or more reference implementation PRs in [the openTDF project's reference implementation](https://github.com/opentdf) -Changes must update version numbers as required (see [guidelines](#version-changes)). +Proposed changes must specify what kind of semver change they would cause - (see [guidelines](#version-changes)). * _Major_ version changes must include a detailed writeup motivating the change and its impact. These PRs must be left open for review for at least 7 days. * _Minor_ version changes must include a brief writeup motivating the change and its impact. These PRs must be left open for review for at least 3 days. +* _Patch_ version changes must include a brief writeup motivating the change and its impact. These PRs must be left open for review for at least 3 days. ### Version Changes We follow the [semver](https://semver.org/spec/v2.0.0.html) guidelines on version changes, although reviewers may exercise their discretion on individual PRs. -* _Major_ version revs when a backwards-incompatible change is made. (Example: new required manifest fields or new required API call.) -* _Minor_ version revs when backwards-compatible functionality is added. (Example: new optional API parameter.) +* _Major_ version revs when a backwards-incompatible change is made that would break clients. (Example: new required manifest fields or new required API call, or client code changes required) +* _Minor_ version revs when backwards-compatible functionality is added that would not break clients. (Example: new optional API parameter.) * _Patch_ version revs when a change does not affect functionality but could affect how readers interpret the spec. (Example: Substantive new diagram illustrating a previously poorly-documented protocol interaction.) * Cosmetic changes should _not_ affect the version number. (Example: Fixing typos, reformatting docs.) diff --git a/ClaimsObject.md b/ClaimsObject.md deleted file mode 100755 index 55e4181..0000000 --- a/ClaimsObject.md +++ /dev/null @@ -1,58 +0,0 @@ -# Claims Object - -## What is this? - -The Claims Object is a JSON object used to ensure that subjects -attempting to decrypt an encrypted file under the Trusted Data Format -have all permissions required to do so. - -The term `Subject` is a generic term that refers to both Person Entities (PE) -and Non-Person Entities (NPE). Subjects are also sometimes referred to as "actors" -in ABAC systems. - -## How does it work? - -When a subject wishes to decrypt a file, the following steps using -the Claims Object are made: - -1. The TDF client requests an OIDC Bearer Token by first authenticating via the -OpenID Connect (OIDC) Identity Provider (IdP) with Custom Claims -support (in this case Keycloak), and if subject authentication succeeds, a -[TDF Claims Object](../schema/ClaimsObject.md) is obtained from -Attribute Provider and signed by the IdP. The signed OIDC Bearer Token is -returned to the client with the Claims Object inside. The Claims -Object contains [AttributeObjects](AttributeObject.md) the subject has -been entitled with. - -2. The client requests a decrypt from the Key Access Server (KAS), -presenting the OIDC Bearer Token (containing the Claims Object) to the KAS. -The KAS ensures that the requestor has the correct permissions to access -the contents of the file by: - -- Examining the validity of the OIDC Bearer Token signature. -- Validating that the Claims Object contains the client's public signing key. -- Validating that the request signature in the client payload can be validated -with the client's public signing key embedded in the OIDC Bearer Token -- Determining if the TDF Client has all the required Attributes and is on - the [Policy Object](PolicyObject.md). - -If these requirements are met, the KAS will permit a decrypt of the file. - -## Example - -```javascript -{ - "subject_attributes": [ - {"attribute": "https://example.com/attr/Classification/value/S", "displayName": "classification"}, - {"attribute": "https://example.com/attr/COI/value/PRX", "displayName": "category of intent"} - ], - "client_public_signing_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy18Efi6+3vSELpbK58gC\nA9vJxZtoRHR604yi707h6nzTsTSNUg5mNzt/nWswWzloIWCgA7EPNpJy9lYn4h1Z\n6LhxEgf0wFcaux0/C19dC6WRPd6 ... XzNO4J38CoFz/\nwwIDAQAB\n-----END PUBLIC KEY-----", - "tdf_spec_version:": "x.y.z" -} -``` - -|Parameter|Type|Description|Required?| -|---|---|---|---| -|`subject_attributes`|Array|An array of [Attribute Objects](AttributeObject.md) that entitle the subject. -|`client_public_signing_key`|String|The TDF Client's public signing key, in a PEM-encoded format. |Yes| -|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| diff --git a/HtmlProtocolExample.html b/HtmlProtocolExample.html deleted file mode 100644 index b306bba..0000000 --- a/HtmlProtocolExample.html +++ /dev/null @@ -1,188 +0,0 @@ - - - - - - - - - -
- - - -
-
-
- - Artboard - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
� Copyright 2019 Virtru Corporation Learn more at www.virtru.com
- - - \ No newline at end of file diff --git a/KeyAccessObject.md b/KeyAccessObject.md deleted file mode 100755 index ace73b8..0000000 --- a/KeyAccessObject.md +++ /dev/null @@ -1,39 +0,0 @@ -# Key Access Object - -## Summary -A Key Access Object stores not only a wrapped (encrypted) key used to encrypt the file's payload, but also additional metadata about _how_ it is stored. - -## Example" - -```javascript -{ - "type": "wrapped", - "url": "https:\/\/kas.example.com:5000", - "protocol": "kas", - "wrappedKey": "OqnOETpwyGE3PVpUpwwWZoJTNW24UMhnXIif0mSnqLVCUPKAAhrjeue11uAXWpb9sD7ZDsmrc9ylmnSKP9vWel8ST68tv6PeVO+CPYUND7cqG2NhUHCLv5Ouys3Klurykvy8\/O3cCLDYl6RDISosxFKqnd7LYD7VnxsYqUns4AW5\/odXJrwIhNO3szZV0JgoBXs+U9bul4tSGNxmYuPOj0RE0HEX5yF5lWlt2vHNCqPlmSBV6+jePf7tOBBsqDq35GxCSHhFZhqCgA3MvnBLmKzVPArtJ1lqg3WUdnWV+o6BUzhDpOIyXzeKn4cK2mCxOXGMP2ck2C1a0sECyB82uw==", - "policyBinding": { - "alg": "HS256", - "hash": "BzmgoIxZzMmIF42qzbdD4Rw30GtdaRSQL2Xlfms1OPs=" - }, - "encryptedMetadata": "ZoJTNW24UMhnXIif0mSnqLVCU=", - "tdf_spec_version:": "x.y.z" -} -``` - - -## keyAccess - -|Parameter|Type|Description|Required?| -|---|---|---|---| -|`keyAccess`|Object|KeyAccess object stores all information about how an object key OR key split is stored, and if / how it has been encrypted (e.g., with KEK or pub wrapping key).|Yes| -|`type`|String|Specifies how the key is stored.

Possible Values:

remote
The wrapped key (see below) is stored using Virtru infrastructure and is thus not part of the final TDF manifest.
wrapped
Default for TDF3, the wrapped key is stored as part of the manifest.
remoteWrapped
Allows management of customer hosted keys, such as with a [Customer Key Server](https://www.virtru.com/faq/virtru-customer-key-server/). This feature is available as an upgrade path.
|Yes| -|`url`|String|A url pointing to the desired KAS deployment|Yes| -|`protocol`|String|Protocol being used. Currently only `kas` is supported|Yes| -|`wrappedKey`|String|The symmetric key used to encrypt the payload. It has been encrypted using the public key of the KAS, then base64 encoded.|Yes| -|`policyBinding`|Object|Object describing the policyBinding. Contains a hash, and an algorithm used.|Yes| -|`policyBinding.alg`|String|The policy binding algorithm used to generate the hash.|Yes| -|`policyBinding.hash`|String|This contains a keyed hash that will provide cryptographic integrity on the policy object, such that it cannot be modified or copied to another TDF, without invalidating the binding. Specifically, you would have to have access to the key in order to overwrite the policy.

This is Base64 encoding of HMAC(POLICY,KEY), where:

POLICY
`base64(policyjson)` that is in the “encryptionInformation/policy”
HMAC
HMAC SHA256 (default, but can be specified in the alg field described above)
KEY
Whichever Key Split or Key that is available to the KAS (e.g. the underlying AES 256 key in the wrappedKey.
|Yes| -|`encryptedMetadata`|String|Metadata associated with the TDF, and the request. The contents of the metadata are freeform, and are used to pass information from the client, and any plugins that may be in use by the KAS. For example, in Virtru's scenario, we could include information about things like, watermarking, expiration, and also data about the request.

Note: `encryptedMetadata` is stored as [a base64-encoded string](https://en.wikipedia.org/wiki/Base64#Base64_table). One example of the metadata, decoded and decrypted, could be, depending on specific needs:

{authHeader:"sd9f8dfkjhwkej8sdfj",connectOptions:{url:'http://localhost:4010'}}|Yes| -|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| - -[comment]: <> (FIXME: description formatting) diff --git a/PolicyObject.md b/PolicyObject.md deleted file mode 100755 index 5b64ad5..0000000 --- a/PolicyObject.md +++ /dev/null @@ -1,39 +0,0 @@ -# Policy Object - -## Summary -The Policy Object is defined by the client at the time of the payload's encryption. It contains the information required by the KAS to make an access decision during decryption. The policyObject is stored in the [manifest.json](manifest-json.md) for a TDF, and sent to the KAS along with an OIDC bearer token containing a [Claims Object](ClaimsObject.md) so that the KAS may make an access decision. - -The KAS uses the Policy Object to make its decision to grant access to the TDF payload. The entity or user requesting access must be in the `dissem` (dissemination) list _AND_ must possess entity attributes (as returned by the EAS) that satisfy all the data [Attributes](AttributeObject.md). - -## Example - -```javascript -{ -"uuid": "1111-2222-33333-44444-abddef-timestamp", -"body": { - "dataAttributes": [], - "dissem": ["user-id@domain.com"] - }, -"tdf_spec_version:": "x.y.z" -} -``` - -## uuid - -|Parameter|Type|Description| -|---|---|---| -|`uuid`|String|A unique [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) for the TDF's policy.| - -## body - -|Parameter|Type|Description|Required?| -|---|---|---|---| -|`body`|Object|Object which contains information about the policy required for the KAS to make an access decision.|Yes| -|`body.dataAttributes`|Array|An array of attributes a user would need to request access to key. In other words, attributes a user must possess to be able to decrypt the content. An Attribute Object is defined in defined in its own section: [Attribute Object](AttributeObject.md).|Yes| -|`body.dissem`|Array|An array of unique userIds. It's used to explicitly list users/entities that should be given access to the payload, and should be given as an id used to authenticate the user against the EAS.|Yes| - -## tdf_spec_version - -|Parameter|Type|Description|Required?| -|---|---|---|---| -|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| diff --git a/api/kas-api.yaml b/api/kas-api.yaml index 7fdca62..09dc360 100644 --- a/api/kas-api.yaml +++ b/api/kas-api.yaml @@ -170,11 +170,11 @@ components: oneOf: - type: object required: - - clientPayloadSignature + - signedRequestToken - keyAccess maxProperties: 5 properties: - clientPayloadSignature: + signedRequestToken: $ref: "#/components/schemas/AuthToken" keyAccess: $ref: "#/components/schemas/KeyAccess" diff --git a/manifest-json.md b/manifest-json.md deleted file mode 100755 index 44f97ad..0000000 --- a/manifest-json.md +++ /dev/null @@ -1,163 +0,0 @@ -# manifest.json - -## Summary -In order to decrypt an encrypted TDF payload (such as an image, text file, etc.), there needs to be a location in which to store supporting data and metadata regarding its encryption details. - -A TDF's manifest holds this information, and is used by a client in its request to the KAS to supply the necessary keys such that the client can decrypt its payload. It describes the location of the payload , the method used to encrypt it, information to verify its authenticity, the KASes a client must make requests to in order to get an unwrapped key, etc. It also contains the TDF's policy which describes who, or what should be given access to the content. - -## At a Glance -From the top level, the TDF manifest contains only two properties: `payload` and `encryptionInformation`. Each of which are objects, and are decomposed in their own sections below. - -If you'd like to see a real manifest created using the TDF3 client, check it out [here](#authentic-manifest). - -## payload -The payload contains metadata required to decrypt the TDF's payload, including _how_ to decrypt (protocol), and a reference to the local payload file. - -```javascript -"payload": { - "type": "reference", - "url": "0.payload", - "protocol": "zip", - "isEncrypted": true, - "mimeType": "application/pdf", - "tdf_spec_version:": "x.y.z" -} -``` - -|Parameter|Type|Description|Required?| -|---|---|---|---| -|`type`|String|Type of payload. The type would be a description of where to get the payload. Is it contained within the TDF, for example, or stored on a remote server?\n\nCurrently a type of `reference` is the only possible type.|Yes| -|`url`|String|A url pointing to the location of the payload. For example, `0.payload`, as a file local to the TDF.|Yes| -|`protocol`|String|Designates which protocol was used during encryption. Currently, only `zip` and `zipstream` are supported and are specified at time of encryption depending on the use of non-streaming vs. streaming encryption.|Yes| -|`isEncrypted`|Boolean|Designates whether or not the payload is encrypted. This set by default to `true` for the time being and is intended for later expansion.|Yes| -|`mimeType`|String|Specifies the type of file that is encrypted. Default is `application/octet-stream`. |No| -|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| - -## encryptionInformation -Contains information describing the method of encryption. As well as information about one or more KASes which own the TDF. - -```javascript -"encryptionInformation": { - "type": "split", - "keyAccess": [], - "method": {}, - "integrityInformation": {}, - "policy": "eyJ1dWlkIjoiNGYwYWIxMzEtNGRmZS00YmExLTljMDQtZjIzZTE0MDMyNzZhIiwiYm9keSI6eyJhdHRyaWJ1dGVzIjpbXSwiZGlzc2VtIjpbInVzZXJAdmlydHJ1LmNvbSJdfX0=" -} -``` - -|Parameter|Type|Description| -|---|---|---| -|`type`|String|The type of scheme used for accessing keys, and providing authorization to the payload. The schema supports multiple options, but currently the only option supported by our libraries is `split`.| -|`keyAccess`|Array|An array of keyAccess Objects. This object is defined in its own section: [Key Access Object](KeyAccessObject.md)| -|`method`|Object|The encryption method object is defined below: [method](#encryptioninformationmethod)| -|`integrityInformation`|Object|`integrityInformation` is defined below in its own section: [integrityInformation](#encryptioninformationintegrityinformation)| -|`policy`|String|The policy object which has been JSON stringified, then base64 encoded. The policy object is described in its own section: [Policy Object](PolicyObject.md)| - -## encryptionInformation.method -An object which describes the information required to actually decrypt the payload once the key is retrieved. Includes the algorithm, and iv at a minimum. - -```javascript -"method": { - "algorithm": "AES-256-GCM", - "isStreamable": true, - "iv": "D6s7cSgFXzhVkran" -} -``` - -|Parameter|Type|Description| -|---|---|---| -|`algorithm`|String|The algorithm used for encryption. Currently the two available options are `aes-256-gcm`.| -|`isStreamable`|Boolean|`isStreamable` designates whether or not a TDF payload is streamable. If it's streamable, the payload is broken into chunks, and individual hashes are generated per chunk to establish integrity of the individual chunks.| -|`iv`|String|The initialization vector for the encrypted payload.| - -## encryptionInformation.integrityInformation -An object which allows an application to validate the integrity of the payload, or a chunk of a payload should it be a streamable TDF. - -```javascript -"integrityInformation": { - "rootSignature": { - "alg": "HS256", - "sig": "M2E2MTI5YmMxMWU0ODIzZDA4YTdkNTY2MzdlNDM4OGRlZDE2MTFhZjU1YTY1YzBhYWNlMWVjYjlmODUzNmNiZQ==" - }, - "segmentHashAlg": "GMAC", - "segments": [], - "segmentSizeDefault": 1000000, - "encryptedSegmentSizeDefault": 1000028 -} -``` -|Parameter|Type|Description| -|---|---|---| -|`rootSignature`|Object|Object containing a signature for the entire payload, and the algorithm used to generate it.| -|`rootSignature.alg`|String|The algorithm used to generate the root signature. `HS256` is the only available option currently.| -|`rootSignature.sig`|String|The signature for the entire payload. \n\nExample of signature generation:\n`Base64.encode(HMAC(BinaryOfAllHashesCombined, payloadKey))`| -|`segmentHashAlg`|String|The name of the hashing algorithm used to generate the hashes for each segment. Currently only `GMAC` is available.| -|`segments`|Array|An array of objects containing each segment object. A segment is defined in its own section: [segment](#encryptioninformationintegrityinformationsegment)| -|`segmentSizeDefault`|Number|The default size of each chunk, or segment in bytes. By setting the default size here, the segments array becomes more space efficient as it will not have to specify the segment size each time.| -|`encryptedSegmentSizeDefault`|Number|Similar to `segmentSizeDefault` - the default size of each chunk of _encrypted_ data, in bytes.| - -## encryptionInformation.integrityInformation.segment -Object containing integrity information about a segment of the payload, including its hash. - -```javascript -{ - "hash": "NzhlZDg5OWMwZWVhZDBjMWEzZTQyYmFlODA0NjNlMDM=", - "segmentSize": 14056, - "encryptedSegmentSize": 14084 -} -``` - -|Parameter|Type|Description| -|---|---|---| -|`hash`|String|A hash generated using the specified 'segmentHashAlg'. `Base64.encode(HMAC(segment, payloadKey))`| -|`segmentSize`|Number|The size of the segment. This field is optional. The size of the segment is inferred from 'segmentSizeDefault' defined above, but in the event that a segment were modified and re-encrypted, the segment size would change.| -|`encryptedSegmentSize`|Number|The size of the segment (in bytes) after the payload segment has been encrypted.| - -## Authentic Manifest -Here is the JSON from an actual `.tdf` file, created by the TDF3 client. - -```javascript -{ - "payload": { - "type": "reference", - "url": "0.payload", - "protocol": "zip", - "isEncrypted": true - }, - "encryptionInformation": { - "type": "split", - "keyAccess": [ - { - "type": "wrapped", - "url": "http://kas.example.com:4000", - "protocol": "kas", - "wrappedKey": "YBkqvsiDnyDfw5JQzux2S2IaiClhsojZuLYY9WOc9N9l37A5/Zi7iloxcqgFvBFbzVjGW4QBwAHsytKQvE87bHTuQkZs4XyPACOZE/k9r+mK8KazcGTkOnqPKQNhf2XK4TBACJZ6eItO5Q1eHUQVLKjxUfgyx2TBDfhB/7XifNthu+6lFbKHmPl1q7q1Vaa/rpPRhSgqf89x5fQvcSWdkuOH9Y4wTa8tdKqSS3DUNMKTIUQq8Ti/WFrq26DRemybBgBcL/CyUZ98hFjDQgy4csBusEqwQ5zG+UAoRgkLkHiAw7hNAayAUCVRw6aUYRF4LWfcs2BM9k6d3bHqun0v5w==", - "policyBinding": "ZGMwNGExZjg0ODFjNDEzZTk5NjdkZmI5MWFjN2Y1MzI0MTliNjM5MmRlMTlhYWM0NjNjN2VjYTVkOTJlODcwNA==", - "encryptedMetadata": "OEOqJCS6mZsmLWJ38lh6EN2lDUA8OagL/OxQRQ==" - } - ], - "method": { - "algorithm": "AES-256-GCM", - "isStreamable": true, - "iv": "OEOqJCS6mZsmLWJ3" - }, - "integrityInformation": { - "rootSignature": { - "alg": "HS256", - "sig": "YjliMzAyNjg4NzA0NzUyYmUwNzY1YWE4MWNhNDRmMDZjZDU3OWMyYTMzNjNlNDYyNTM4MDA4YjQxYTdmZmFmOA==" - }, - "segmentSizeDefault": 1000000, - "segmentHashAlg": "GMAC", - "segments": [ - { - "hash": "ZmQyYjY2ZDgxY2IzNGNmZTI3ODFhYTk2ZjJhNWNjODA=", - "segmentSize": 14056, - "encryptedSegmentSize": 14084 - } - ], - "encryptedSegmentSizeDefault": 1000028 - }, - "policy": "eyJ1dWlkIjoiNjEzMzM0NjYtNGYwYS00YTEyLTk1ZmItYjZkOGJkMGI4YjI2IiwiYm9keSI6eyJhdHRyaWJ1dGVzIjpbXSwiZGlzc2VtIjpbInVzZXJAdmlydHJ1LmNvbSJdfX0=" - } -} -``` diff --git a/protocol/README.md b/protocol/README.md index 7be5f4b..f0f9b5d 100755 --- a/protocol/README.md +++ b/protocol/README.md @@ -6,21 +6,54 @@ This document describes the canonical system architecture used to encrypt and de The canonical architecture contains four major components. -* *TDF Client* - Initiates and drives the TDF encryption and decryption workflows. Only component with access to the content (ciphertext or plaintext). -* *OpenID Connect (OIDC) Identity Provider (IdP)* - This system could be any OIDC IdP software. Virtru has chosen Keycloak as its reference implementation IdP. +* *TDF Client* - Initiates and drives the TDF encryption and decryption workflows. Only component with access to the content (ciphertext or plaintext). + * May be entitled as Non-Person Entity acting on behalf of itself, OR on behalf of a Person Entity. +* *OpenID Connect (OIDC) Identity Provider (IdP)* - This system could be any OIDC IdP software. OpenTDF has chosen Keycloak as its reference implementation IdP. * From Wikipedia: "Keycloak is an open source software product to allow single sign-on with Identity and Access Management aimed at modern applications and services. As of March 2018 this JBoss community project is under the stewardship of Red Hat. Keycloak is licensed under Apache 2.0." * Any OIDC-compliant IdP software may be used, provided it supports custom claims, and can: * Read the TDF Client public key from a custom HTTP header sent with the OIDC authentication request. * Construct and send an Attribute Provider web service request, including the public key in the payload. * Return the resulting Claims Object in the signed IdP JWT. * A list of Certified OpenID Connect applications can be found at: https://openid.net/developers/certified/ - * *Virtru Protocol Mapper* (PM) is Virtru's Keycloak-specific reference implementation of the above functionality. -* *Attribute Provider* (AP) - A web service that receives requests which contain information about the authenticated subject from an OIDC IdP with custom claims support (ex: Keycloak with Virtru Protocol Mapper), and returns custom TDF OIDC claims in response. It is the responsibility of Attribute Provider to transform incoming 3rd party IdP claims/metadata to a set of outgoing [Attribute Objects](../schema/AttributeObject.md). It returns a TDF [Claims Object](../schema/ClaimsObject.md). -* *Key Access Service* (KAS) - Responsible for authorizing and granting TDF Clients access to rewrapped data key material. If authorized, TDF Clients can use this rewrapped data key to decrypt TDF ciphertext. A valid OIDC token containing [TDF Claims](../schema/ClaimsObject.md) must be used as a bearer token when communicating with KAS. KAS will first verify the authenticity of the bearer token and then the policy claims within that bearer token. An otherwise valid and trusted OIDC token without valid TDF Claims will be rejected. + * *OpenTDF Protocol Mapper* (PM) is OpenTDF's Keycloak-specific reference implementation of the above functionality. +* *Attribute Provider* (AP) - A web service that receives requests which contain information about the authenticated entities from an OIDC IdP with custom claims support (ex: Keycloak with OpenTDF Protocol Mapper), and returns custom TDF OIDC claims in response. It is the responsibility of Attribute Provider to transform incoming 3rd party IdP claims/metadata to a set of outgoing [Attribute Objects](../schema/AttributeObject.md). It returns a TDF [Claims Object](../schema/ClaimsObject.md). +* *Key Access Service* (KAS) - Responsible for authorizing and granting TDF Clients access to rewrapped data key material. If authorized, TDF Clients (on behalf of themselves, or other entities) can use this rewrapped data key to decrypt TDF ciphertext. A valid OIDC token containing [TDF Claims](../schema/ClaimsObject.md) must be used as a bearer token when communicating with KAS. KAS will verify the authenticity of the bearer token, the request signature, and then the policy claims within that bearer token. An otherwise valid and trusted OIDC token without valid TDF Claims will be rejected. -## Workflow +## General Authentication Protocol -The following sequence diagrams illustrate the client workflow for encrypting or decrypting TDF ciphertext. The canonical TDF architecture supports two modes of operation: _online mode_ and _offline mode_, which have distinct workflows as shown below. +OIDC Auth with a PoP scheme is used for **all** TDF Client interactions with backend TDF services: + +1. The TDF Client requests an OIDC Bearer Token (either on behalf of itself, or another entity) +by first authenticating via the OpenID Connect (OIDC) Identity Provider (IdP) with Custom Claims +support (in this example, Keycloak). As part of this authentication process, the TDF Client **must** convey its signing public key to the IdP. + * If the TDF Client public signing key is rotated or changed, a new OIDC Bearer Token must be obtained from the IdP, containing the TDF Client's new public signing key. + * It should be assumed that the TDF Client's signing keypair is ephemeral, and that the TDF Client's _private_ signing key is known only to the TDF Client. + * Measures should be taken to protect all TDF Client private keys, but the mechanisms for doing so are outside the scope of this spec. + +1. If entity authentication succeeds, a +[TDF Claims Object](../schema/ClaimsObject.md) is obtained from +Attribute Provider and signed by the IdP. The signing public key previously conveyed by the TDF Client is embedded within the [TDF Claims Object](../schema/ClaimsObject.md). +The signed OIDC Bearer Token is then returned to the TDF Client, containing the complete [TDF Claims Object](../schema/ClaimsObject.md). + * The [TDF Claims Object](../schema/ClaimsObject.md) contains one or more [Entitlement Objects](EntitlementObject.md) entitling all entities +involved in the authentication request. + +1. The TDF Client must convey the IdP-signed OIDC Bearer Token to backend services with all requests, and in addition, the TDF Client **must** sign all requests to backend services with its _private signing key_ + * The request signature should be a signature of the entire request body, sans the request signature itself. + * For HTTPS, it should be considered best practice to insert the request signature itself in the request body rather than send it as a custom header. + +1. Backend services are required to: + * Validate AuthN: + * Examine the validity of the OIDC Bearer Token signature by contacting the issuing IdP. + * Validate that the [TDF Claims Object](../schema/ClaimsObject.md) contains a TDF Client public signing key. + * Validate that the request signature in the TDF Client's payload **can be validated** with the TDF Client's public signing key embedded in the OIDC Bearer Token associated with the signed request + * Validate AuthZ (if necessary) + * Determine if all the entities entitled in the presented bearer token have all the required Attributes for a given operation, as per service requirements. + +If these requirements are met, a TDF Client may be considered authenticated and authorized. + +### Diagrams + +The following sequence diagrams illustrate the TDF Client workflow for encrypting or decrypting TDF ciphertext. The canonical TDF architecture supports two modes of operation: _online mode_ and _offline mode_, which have distinct workflows as shown below. _Online mode_ is the default mode, where the [wrapped data key](../schema/KeyAccessObject.md) and [authorization policy](../schema/PolicyObject.md) for TDF ciphertext is committed to KAS in-band as part of the `encrypt` operation. This means that the `encrypt` will succeed if and only if all resources are prepared to facilitate an immediate decrypt. @@ -28,7 +61,7 @@ _Offline mode_ requires that the TDF Client previously obtained a long-lived TDF JWT with embedded Claims Object via online OIDC authentication. Or, the TDF Client has otherwise obtained a valid signed JWT with embedded Claims Object through offline means -(ex: generated by a script using the IdP signing key). Clients +(ex: generated by a script using the IdP signing key). TDF Clients running in this mode commit the [authorization policy](../schema/PolicyObject.md) out-of-band, or when decrypt is first performed. This significantly reduces latency at the cost of a diff --git a/schema/AttributeObject.md b/schema/AttributeObject.md index 3f37fbe..2ab4924 100644 --- a/schema/AttributeObject.md +++ b/schema/AttributeObject.md @@ -1,46 +1,41 @@ # Attribute Object ## Summary -An Attribute Object contains attribute information the TDF3 system uses to enforce attribute-based access control (ABAC). Attributes are used in both the [PolicyObject](PolicyObject.md) to define the attributes that a subject "needs" to gain access in an ABAC sense, and in the [ClaimsObject](ClaimsObject.md) to assert the attributes that an actor "has". -Access decisions are made by comparing the attributes a subject has with the attributes a policy requires. +An Attribute Object contains attribute information the TDF system uses to enforce attribute-based access control (ABAC). -Attributes that a subject (or actor, or entity) "has" are referred to as "subject attributes". +Attributes are used in both the [Policy Object](PolicyObject.md) to define the attributes that an entity "needs" to gain access to data in an ABAC sense, +and in the [Entitlement Object](EntitlementObject.md) to assert the attributes that an entity "has". -Attributes that subjects "need" in order to access data are referred to as "object attributes". +Access decisions are made by comparing the attributes all entities have with the attributes a data policy requires. -The _attribute_ field must be both unique and immutable as it is the reference id for the attribute. All of the other fields are mutable. The attribute string contains three pieces of information - the authority namespace, the attribute name, and the attribute value. +Attributes that an entity (or actor, or subject) "has" are referred to as "entity entitlements" and are represented by [Entitlement Objects](EntitlementObject.md) -When encrypting, the client determines which attributes a subject must have in order to decrypt the payload and applies those attributes to the file's [Policy Object](PolicyObject.md). +Attributes that entities "need" in order to access data are referred to as "data attributes" and are represented by [Policy Objects](PolicyObject.md) + +The set of all entity entitlements involved in a request are referred to as "claims" and are represented by a [Claims Object](ClaimsObject.md) + +The _attribute_ field must be both globally unique and immutable as it is the reference id for the attribute. +All of the other fields are mutable. The attribute string contains three pieces of information - the authority namespace, the attribute name, and the attribute value. + +When encrypting, the client determines which attributes an entity must have in order to decrypt the payload and applies those attributes to the file's [Policy Object](PolicyObject.md). When a decrypt is requested, the KAS checks the [Policy Object](PolicyObject.md) against the [Claims Object](ClaimsObject.md) from the requesting client to ensure the attributes that an entity "has" satisfies those that an entity "needs". If this check succeeds, the KAS permits a decrypt operation and returns a valid key which the client can decrypt and use to expose the file contents. -The public key is used to wrap the object key or key splits on TDF3 file creation. On decrypt, the kasUrl defines where this key or key split can be rewrapped. - -The AttributeObject alone does not define how the KAS will compare a subject attribute to an object attribute when making an access decision. -The KAS uses the namespaced object attributes in the [PolicyObject](PolicyObject.md) look up attribute policies from the cognizant authority +The AttributeObject alone does not define how the KAS will compare an entity's attribute to an object attribute when making an access decision. +The KAS uses the namespaced object attributes in the [Policy Object](PolicyObject.md) to look up attribute policies from the cognizant authority to make its policy decisions. Clients writing policies should use best available information from their organizations to select which AttributeObjects to include to protect the policy. ## Example ```javascript { - "attribute": "https://example.com/attr/classification/value/topsecret", - "isDefault": true, - "displayName": "classification", - "pubKey": "pem encoded public key of the attribute", - "kasUrl": "https://kas.example.com/", - "tdfVersion:": "x.y.z" + "attribute": "https://example.com/attr/classification/value/topsecret" } ``` |Parameter|Type|Description|Required?| |---|---|---|---| |`attribute`|String|Also known as the "attribute url." The unique resource name for the attribute represented as a case-insensitive URL string. This field must be both unique and immutable as it is the reference id for the attribute. The attribute URL string contains three pieces of information - in the above example, the authority namespace (https://example.com), the attribute name (classification), and the attribute value (topsecret). |Yes| -|`isDefault`|Boolean|If "true" this flag identifies the attribute as the default attribute. If missing (preferred) or false then the attribute is not the default attribute.|No| -|`displayName`|String|A human-readable nickname for the attribute for convenience.|Yes| -|`pubKey`|PEM|PEM encoded public key for this attribute. Often other attributes will use the same pubKey.|Yes| -|`kasUrl`|URL|Base URL of a KAS that can make access control decisions for this attribute.|Yes| -|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| diff --git a/schema/ClaimsObject.md b/schema/ClaimsObject.md index 55e4181..fdb5ea7 100755 --- a/schema/ClaimsObject.md +++ b/schema/ClaimsObject.md @@ -2,39 +2,43 @@ ## What is this? -The Claims Object is a JSON object used to ensure that subjects +The Claims Object is a JSON object used to ensure that entities attempting to decrypt an encrypted file under the Trusted Data Format have all permissions required to do so. -The term `Subject` is a generic term that refers to both Person Entities (PE) -and Non-Person Entities (NPE). Subjects are also sometimes referred to as "actors" +The term `Entity` is a generic term that refers to both Person Entities (PE) +and Non-Person Entities (NPE). Entities are also sometimes referred to as "actors" or "subjects" in ABAC systems. +Under this definition, *both* the human user attempting to authenticate, and the specific TDF client they are using to authenticate with would be classified as Entities - a PE and an NPE respectively. + ## How does it work? -When a subject wishes to decrypt a file, the following steps using -the Claims Object are made: +When an entity (either on behalf of itself, or another entity) wishes to decrypt a file, +the following happens: -1. The TDF client requests an OIDC Bearer Token by first authenticating via the +1. The TDF client requests an OIDC Bearer Token (either on behalf of itself, or another entity) +by first authenticating via the OpenID Connect (OIDC) Identity Provider (IdP) with Custom Claims -support (in this case Keycloak), and if subject authentication succeeds, a +support (in this case Keycloak), and if entity authentication succeeds, a [TDF Claims Object](../schema/ClaimsObject.md) is obtained from Attribute Provider and signed by the IdP. The signed OIDC Bearer Token is -returned to the client with the Claims Object inside. The Claims -Object contains [AttributeObjects](AttributeObject.md) the subject has -been entitled with. +returned to the client with the Claims Object inside. + +The Claims Object contains one or more [Entitlement Objects](EntitlementObject.md) entitling all entities +involved in the authentication request. 2. The client requests a decrypt from the Key Access Server (KAS), -presenting the OIDC Bearer Token (containing the Claims Object) to the KAS. -The KAS ensures that the requestor has the correct permissions to access -the contents of the file by: +presenting the OIDC Bearer Token (containing the Claims Object) to the KAS. +The KAS ensures that all entities entitled in the OIDC bearer token have the +correct permissions to access the contents of the file by: - Examining the validity of the OIDC Bearer Token signature. - Validating that the Claims Object contains the client's public signing key. - Validating that the request signature in the client payload can be validated with the client's public signing key embedded in the OIDC Bearer Token -- Determining if the TDF Client has all the required Attributes and is on - the [Policy Object](PolicyObject.md). +- Determining if all the entities entitled in the presented bearer token have all the required Attributes, +according to PDP rules. If these requirements are met, the KAS will permit a decrypt of the file. @@ -42,17 +46,41 @@ If these requirements are met, the KAS will permit a decrypt of the file. ```javascript { - "subject_attributes": [ - {"attribute": "https://example.com/attr/Classification/value/S", "displayName": "classification"}, - {"attribute": "https://example.com/attr/COI/value/PRX", "displayName": "category of intent"} + "entitlements":[ + { + "entity_identifier":"cliententityid-14443434-1111343434-asdfdffff", + "entity_attributes":[ + { + "attribute":"https://example.com/attr/Classification/value/S", + "displayName":"classification" + }, + { + "attribute":"https://example.com/attr/COI/value/PRX", + "displayName":"category of intent" + } + ] + }, + { + "entity_identifier":"dd-ff-eeeeee1134r34434-user-beta", + "entity_attributes":[ + { + "attribute":"https://example.com/attr/Classification/value/U", + "displayName":"classification" + }, + { + "attribute":"https://example.com/attr/COI/value/PRZ", + "displayName":"category of intent" + } + ] + } ], - "client_public_signing_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy18Efi6+3vSELpbK58gC\nA9vJxZtoRHR604yi707h6nzTsTSNUg5mNzt/nWswWzloIWCgA7EPNpJy9lYn4h1Z\n6LhxEgf0wFcaux0/C19dC6WRPd6 ... XzNO4J38CoFz/\nwwIDAQAB\n-----END PUBLIC KEY-----", - "tdf_spec_version:": "x.y.z" + "client_public_signing_key":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy18Efi6+3vSELpbK58gC\nA9vJxZtoRHR604yi707h6nzTsTSNUg5mNzt/nWswWzloIWCgA7EPNpJy9lYn4h1Z\n6LhxEgf0wFcaux0/C19dC6WRPd6 ... XzNO4J38CoFz/\nwwIDAQAB\n-----END PUBLIC KEY-----", + "tdf_spec_version:":"x.y.z" } ``` -|Parameter|Type|Description|Required?| -|---|---|---|---| -|`subject_attributes`|Array|An array of [Attribute Objects](AttributeObject.md) that entitle the subject. -|`client_public_signing_key`|String|The TDF Client's public signing key, in a PEM-encoded format. |Yes| -|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| +| Parameter | Type | Description | Required? | +|-----------------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------|--------------------| +| `entitlements` | Array | An array of [Entitlement Objects](EntitlementObject.md) for each entity (PE or NPE) involved in the authentication request. | Yes | +| `client_public_signing_key` | String | The TDF Client's public signing key, in a PEM-encoded format. | Yes | +| `tdf_spec_version` | String | Semver version number of the TDF spec. | No | diff --git a/schema/EntitlementObject.md b/schema/EntitlementObject.md new file mode 100644 index 0000000..7798bf7 --- /dev/null +++ b/schema/EntitlementObject.md @@ -0,0 +1,35 @@ +# Entitlement Object + +## Summary +An Entitlement Object represents a complete set of entitlements (that is, a set of [Attribute Objects](AttributeObject.md)) for a single Entity (PE or NPE). + +An Entitlement Object defines the attributes a single Entity (PE or NPE) _is entitled with_. + +A [Claims Object](ClaimsObject.md) is composed of one or more Entitlement Objects. + +Access decisions are made by comparing the attribute entitlements of one or more entities against the attributes a data policy requires. + +The Entitlement Object alone _does not_ define how the KAS will compare an entity's attribute to an object attribute when making an access decisions, as there may be multiple Entitlement Objects involved in an access request. + +## Example + +```javascript +{ + "entity_identifier":"cliententityid-14443434-1111343434-asdfdffff", + "entity_attributes":[ + { + "attribute":"https://example.com/attr/Classification/value/S", + "displayName":"classification" + }, + { + "attribute":"https://example.com/attr/COI/value/PRX", + "displayName":"category of intent" + } + ] +} +``` + +| Parameter | Type | Description | Required? | +|-----------------------------|--------|------------------------------------------------------------------------------------------------------------------------------------------|--------------------| +| `entity_identifier`| String | An identifer for the entitled entity. Note that this field is purely informational - *no access decisions* should depend on this value. | Yes | +| `entity_attributes`| Array | An array of [Attribute Objects](AttributeObject.md) that entitle the given entity. | Yes (can be empty) | diff --git a/schema/KeyAccessObject.md b/schema/KeyAccessObject.md index ace73b8..9e4af56 100755 --- a/schema/KeyAccessObject.md +++ b/schema/KeyAccessObject.md @@ -26,14 +26,14 @@ A Key Access Object stores not only a wrapped (encrypted) key used to encrypt th |Parameter|Type|Description|Required?| |---|---|---|---| |`keyAccess`|Object|KeyAccess object stores all information about how an object key OR key split is stored, and if / how it has been encrypted (e.g., with KEK or pub wrapping key).|Yes| -|`type`|String|Specifies how the key is stored.

Possible Values:

remote
The wrapped key (see below) is stored using Virtru infrastructure and is thus not part of the final TDF manifest.
wrapped
Default for TDF3, the wrapped key is stored as part of the manifest.
remoteWrapped
Allows management of customer hosted keys, such as with a [Customer Key Server](https://www.virtru.com/faq/virtru-customer-key-server/). This feature is available as an upgrade path.
|Yes| +|`type`|String|Specifies how the key is stored.

Possible Values:

remote
The wrapped key (see below) is stored using Virtru infrastructure and is thus not part of the final TDF manifest.
wrapped
Default for TDF 3.x and newer, the wrapped key is stored as part of the manifest.
remoteWrapped
Allows management of customer hosted keys, such as with a [Customer Key Server](https://www.virtru.com/faq/virtru-customer-key-server/). This feature is available as an upgrade path.
|Yes| |`url`|String|A url pointing to the desired KAS deployment|Yes| |`protocol`|String|Protocol being used. Currently only `kas` is supported|Yes| |`wrappedKey`|String|The symmetric key used to encrypt the payload. It has been encrypted using the public key of the KAS, then base64 encoded.|Yes| |`policyBinding`|Object|Object describing the policyBinding. Contains a hash, and an algorithm used.|Yes| |`policyBinding.alg`|String|The policy binding algorithm used to generate the hash.|Yes| |`policyBinding.hash`|String|This contains a keyed hash that will provide cryptographic integrity on the policy object, such that it cannot be modified or copied to another TDF, without invalidating the binding. Specifically, you would have to have access to the key in order to overwrite the policy.

This is Base64 encoding of HMAC(POLICY,KEY), where:

POLICY
`base64(policyjson)` that is in the “encryptionInformation/policy”
HMAC
HMAC SHA256 (default, but can be specified in the alg field described above)
KEY
Whichever Key Split or Key that is available to the KAS (e.g. the underlying AES 256 key in the wrappedKey.
|Yes| -|`encryptedMetadata`|String|Metadata associated with the TDF, and the request. The contents of the metadata are freeform, and are used to pass information from the client, and any plugins that may be in use by the KAS. For example, in Virtru's scenario, we could include information about things like, watermarking, expiration, and also data about the request.

Note: `encryptedMetadata` is stored as [a base64-encoded string](https://en.wikipedia.org/wiki/Base64#Base64_table). One example of the metadata, decoded and decrypted, could be, depending on specific needs:

{authHeader:"sd9f8dfkjhwkej8sdfj",connectOptions:{url:'http://localhost:4010'}}|Yes| +|`encryptedMetadata`|String|Metadata associated with the TDF, and the request. The contents of the metadata are freeform, and are used to pass information from the client, and any plugins that may be in use by the KAS. The metadata stored here should not be used for primary access decisions.

Note: `encryptedMetadata` is stored as [a base64-encoded string](https://en.wikipedia.org/wiki/Base64#Base64_table). One example of the metadata, decoded and decrypted, could be, depending on specific needs:

{authHeader:"sd9f8dfkjhwkej8sdfj",connectOptions:{url:'http://localhost:4010'}}|Yes| |`tdf_spec_version`|String|Semver version number of the TDF spec.|No| [comment]: <> (FIXME: description formatting) diff --git a/schema/PolicyObject.md b/schema/PolicyObject.md index 5b64ad5..285af1c 100755 --- a/schema/PolicyObject.md +++ b/schema/PolicyObject.md @@ -30,7 +30,7 @@ The KAS uses the Policy Object to make its decision to grant access to the TDF p |---|---|---|---| |`body`|Object|Object which contains information about the policy required for the KAS to make an access decision.|Yes| |`body.dataAttributes`|Array|An array of attributes a user would need to request access to key. In other words, attributes a user must possess to be able to decrypt the content. An Attribute Object is defined in defined in its own section: [Attribute Object](AttributeObject.md).|Yes| -|`body.dissem`|Array|An array of unique userIds. It's used to explicitly list users/entities that should be given access to the payload, and should be given as an id used to authenticate the user against the EAS.|Yes| +|`body.dissem`|Array|(deprecated) An array of unique userIds. It's used to explicitly list users/entities that should be given access to the payload, and should be given as an id used to authenticate the user against the EAS.|Yes| ## tdf_spec_version diff --git a/schema/README.md b/schema/README.md index b1d2fef..3ae8f51 100644 --- a/schema/README.md +++ b/schema/README.md @@ -1,5 +1,13 @@ # TDF Schemas +Attributes are represented by [Attribute Objects](AttributeObject.md) + +Attributes that an entity (or actor, or subject) "has" are referred to as "entity entitlements" and are represented by [Entitlement Objects](EntitlementObject.md) + +Attributes that entities "need" in order to access data are referred to as "data attributes" and are represented by [Policy Objects](PolicyObject.md) + +The set of all entity entitlements involved in a request are referred to as "claims" and are represented by a [Claims Object](ClaimsObject.md) + A TDF file consists of: * Encrypted payload @@ -10,5 +18,7 @@ The [TDF protocol](https://github.com/virtru/tdf3-spec/tree/master/protocol) als * A [Attribute Object](AttributeObject.md) created by an attribute authority. * A [Policy Object](PolicyObject.md) created by the client and used by the [Key Access Service](https://developer.virtru.com/docs/how-to-host-a-kas) (KAS). * Policy Objects contain [Attribute Objects](AttributeObject.md), describing the object (or data) attributes. +* A [Entitlement Object](EntitlementObjects.md) describing the entitlements of a single entity (or actor, or subject). + * Entitlement Objects contain [Attribute Objects](AttributeObject.md), describing individual entity (or actor, or subject) attributes. * A [Claims Object](ClaimsObject.md) created by the [Attribute Provider](../protocol/README.md) and issued by an OIDC IdP - * Claims Objects contain [Attribute Objects](AttributeObject.md), describing the subject (or actor) attributes. + * Claims Objects contain [Entitlement Objects](EntitlementObjects.md), describing the entitlements of all entities (PE or NPE) involved in an access decision. diff --git a/schema/manifest-json.md b/schema/manifest-json.md index 44f97ad..6e0d251 100755 --- a/schema/manifest-json.md +++ b/schema/manifest-json.md @@ -8,7 +8,7 @@ A TDF's manifest holds this information, and is used by a client in its request ## At a Glance From the top level, the TDF manifest contains only two properties: `payload` and `encryptionInformation`. Each of which are objects, and are decomposed in their own sections below. -If you'd like to see a real manifest created using the TDF3 client, check it out [here](#authentic-manifest). +If you'd like to see a real manifest created using the TDF client, check it out [here](#authentic-manifest). ## payload The payload contains metadata required to decrypt the TDF's payload, including _how_ to decrypt (protocol), and a reference to the local payload file. @@ -114,7 +114,7 @@ Object containing integrity information about a segment of the payload, includin |`encryptedSegmentSize`|Number|The size of the segment (in bytes) after the payload segment has been encrypted.| ## Authentic Manifest -Here is the JSON from an actual `.tdf` file, created by the TDF3 client. +Here is the JSON from an actual `.tdf` file, created by the TDF client. ```javascript { diff --git a/schema/test/README.md b/schema/test/README.md new file mode 100644 index 0000000..f917d21 --- /dev/null +++ b/schema/test/README.md @@ -0,0 +1,3 @@ +# Schema Test Cases + +Validation scripts that can be used to verify data objects adhere to the current schema version.