From 2198db5605ce9d5af05be0eb331cc85dfb6383df Mon Sep 17 00:00:00 2001 From: Ben Leggett <854255+bleggett@users.noreply.github.com> Date: Wed, 15 Sep 2021 13:45:53 -0400 Subject: [PATCH] Update TDF spec to latest design (#27) * Update TDF spec to latest design * Minor fixes * Cosmetic fixes * Prefixing this with `obj` is vestigial, and pointless * Fix typos * Remove stray line * Bring in some ancient fixes from https://github.com/virtru/tdf-spec/pull/19 * Review comments * Update schema/AttributeObject.md Co-authored-by: Dave Mihalcik <38867245+dmihalcik-virtru@users.noreply.github.com> * Drop this * Review comments Co-authored-by: Dave Mihalcik <38867245+dmihalcik-virtru@users.noreply.github.com> --- .github/PULL_REQUEST_TEMPLATE.md | 3 +- CHANGELOG.md | 55 ------ CONTRIBUTING.md | 11 +- VERSION | 2 +- api/README.md | 4 +- api/kas-api.yaml | 295 +++++++++++++++++++++++++++++++ api/kas/swagger.yaml | 142 --------------- protocol/README.md | 14 +- schema/AttributeObject.md | 28 ++- schema/ClaimsAttributeObject.md | 36 ---- schema/ClaimsObject.md | 61 +++---- schema/EntityObject.md | 50 ------ schema/KeyAccessObject.md | 9 +- schema/PolicyObject.md | 15 +- schema/README.md | 14 +- schema/manifest-json.md | 8 +- 16 files changed, 376 insertions(+), 371 deletions(-) delete mode 100644 CHANGELOG.md create mode 100644 api/kas-api.yaml delete mode 100644 api/kas/swagger.yaml delete mode 100644 schema/ClaimsAttributeObject.md delete mode 100755 schema/EntityObject.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2530f69..bf3f6b6 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,7 +5,8 @@ ### Checklist - [ ] A clear description of the change has been included in this PR. -- [ ] The changelog has been updated. +- [ ] 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 -a 4.1.0 -m "Spec version 4.1.0 - did a thing"`) - [ ] 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. diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 0f25706..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,55 +0,0 @@ -# Changelog - -## [Unreleased] -[Unreleased]: https://github.com/virtru/tdf3-spec/compare/master...HEAD -## Added - * _patch_: ([#17](https://github.com/virtru/tdf3-spec/pull/17)) - Add KAS swagger - * _patch_: ([#24](https://github.com/virtru/tdf3-spec/pull/24)), PLAT-897: `EntityObject.signerPublicKey` - - Add a second 'signerPublicKey' field to an EO - - This is an ephemeral public key a client may use to sign rewrap and other requests associated with the EO. - - This is required as some algorithms and key types are more suited for encryption and others for signatures. Notably, we must support this for the smaller keys and restricted set of algorithms that NanoTDF will likely impose - - Implementations: - - Client [nanotdf for javascript](https://github.com/virtru/eternia/pull/78) - - Client [c++](https://github.com/virtru/tdf3-cpp/pull/193) - - Service [OpenStack EAS and KAS (python)](https://github.com/virtru/etheria/pull/295) - -## Changes -* 3.3.4 (2021-05-25) - * _major_ : ([#25](https://github.com/virtru/tdf-spec/pull/25)) - Remove version from repo name, and align semver major version with TDF major version. - This is purely a nonclamenture+versionspec change -* 1.3.4 (2019-08-05) - * _patch_: ([#20](https://github.com/virtru/tdf3-spec/pull/20)) - Update protocol docs and diagrams. -* 1.3.3 (2019-07-14) - * _minor_: ([#16](https://github.com/virtru/tdf3-spec/pull/16)) - Added CODEOWNERS file -* 1.3.2 (2019-07-13) - * _minor_: ([#15](https://github.com/virtru/tdf3-spec/pull/15)) - Added MIT license -* 1.3.1 (2019-06-20) - * _minor_: ([#14](https://github.com/virtru/tdf3-spec/pull/14)) - Example HTML wrapped TDF -* 1.3.0 (2019-06-10) - * _minor_: ([#13](https://github.com/virtru/tdf3-spec/pull/13)) - Added mimeType to allow for reading clients to setup preview experiences. -* 1.2.0 (2019-05-10) - * _minor_: ([#6](https://github.com/virtru/tdf3-spec/pull/6)) - WS-8962/AttributeObject: Added optional 'isDefault' boolean to AO schema. - -* 1.1.1 (2019-05-10) - * _minor_: ([#10](https://github.com/virtru/tdf3-spec/pull/10)) - NOREF: Remove reference to AES-256-CBC, which is not supported. - -* 1.1.0 (2019-04-26) - * _minor_: ([#5](https://github.com/virtru/tdf3-spec/pull/5)) - NOREF: Include version number in data object schemas. - -* 1.0.0 (2019-04-25) - * _none_: ([#3](https://github.com/virtru/tdf3-spec/pull/3)) - NOREF: Reformat CONTRIBUTING doc a bit. - * _none_: ([#2](https://github.com/virtru/tdf3-spec/pull/2)) - NOREF: Make the project README a little slicker. - * _major_: ([#1](https://github.com/virtru/tdf3-spec/pull/1)) - NOREF: Adding initial project structure and docs. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 54c6b59..d3eb3b6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,26 +7,27 @@ Contributions to the TDF3 specification are welcome! Please be sure to follow th 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). Changes must update version numbers as required (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. ### 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.) * _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.) -There are three version numbers which contributors may need to change depending on the type and breadth of the proposed change: -* **Project version** - Version of the top-level project specification. This version should change accordingly if changes are made to the encrypt or decrypt workflow, or if new components or interactions are added to the architecture. Note that the project version isn't necessarily dependent on the API and schema versions, for instance, API parameters or the manifest format can change without affecting the overall workflow. -* **Schema version** - Shared data objects are versioned indepedent of the project version. If the schema for any of these objects changes, then the corresponding schema version should be changed accordingly. -* **API version** - Each swagger-defined API has an associated version number. If the API changes then the corresponding swagger version number should be changed accordingly. +The spec version is this repo's most recent semver Git tag - this means that if the spec version is 4.1.0, then the protocol version and all associated schema versions are also 4.1.0 Any changes that affect _project_ version must update both `git tag` and the [VERSION](VERSION) file. -Any changes that affect _schema_ versions must add or update [validation tests](schema/test/) accordingly. +Rather than use a changelog, we ask that you use annotated `git tags` when bumping the spec Semver, and use the annotation message to describe the change. +> Example: `git tag -a 4.1.0 -m "Spec version 4.1.0 - twiddled a doohickey"`) +A list of `git tag` versions and their annotations can be generated at will via `git tag -n` ## Asking Questions & Submitting Feeback diff --git a/VERSION b/VERSION index 0c89fc9..ee74734 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.0.0 \ No newline at end of file +4.1.0 diff --git a/api/README.md b/api/README.md index ac8476d..fc5af6e 100644 --- a/api/README.md +++ b/api/README.md @@ -1,3 +1,3 @@ -# API +# OpenAPI Specs -This directory contains the swagger definitions for TDF service APIs. +This directory contains example OpenAPI definitions for TDF service APIs. diff --git a/api/kas-api.yaml b/api/kas-api.yaml new file mode 100644 index 0000000..7fdca62 --- /dev/null +++ b/api/kas-api.yaml @@ -0,0 +1,295 @@ +openapi: 3.0.0 +info: + version: 1.0.0 + title: Key Access Service + termsOfService: https://www.virtru.com/terms-of-service/ + contact: + email: support@virtru.com + license: + name: Apache 2.0 + url: 'http://www.apache.org/licenses/LICENSE-2.0.html' + +externalDocs: + description: Developer Hub + url: https://developer.virtru.com/ + +paths: + "/": + get: + summary: Get the current version + description: | + This endpoint is for OPS so they have something to ping on to verify + that the server hasn't died. + responses: + "200": + description: Ok + content: + application/json: + schema: + type: object + properties: + version: + type: string + example: "0.0.0" + + "/kas_public_key": + get: + summary: "Get the public key for KAS" + description: | + This endpoint provides a public key for the private key that the + kas has internally. + parameters: + - name: algorithm + description: algorithm type rsa: or ec: + in: query + schema: + default: rsa:2048 + type: string + responses: + "200": + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/PublicKey" + "404": + description: Not found + + + "/v2/rewrap": + post: + summary: Request a rewrap + description: | + This endpoint performs the primary service of the KAS; to re-wrap + data keys as needed to provide access for entities with a TDF that they + would like to open. + operationId: tdf3_kas_core.web.rewrap.rewrap_v2 + requestBody: + $ref: "#/components/requestBodies/RewrapV2" + # security: + # - virtruOIDCBearerToken: [] + responses: + "200": + description: Ok + content: + application/json: + schema: + type: object + properties: + metadata: + type: object + default: {} + kasWrappedKey: + type: string + nullable: true + entityWrappedKey: + type: string + nullable: true + "400": + $ref: "#/components/responses/BadRequest" + "403": + description: Forbidden + + + "/v2/upsert": + post: + summary: Request a upsert + description: | + The upsert service is a proxy to the back-end services that persist + policies and keys. + requestBody: + $ref: "#/components/requestBodies/UpsertV2" + responses: + "200": + description: Ok + content: + application/json: + schema: + type: array + default: [] + items: {} + "400": + $ref: "#/components/responses/BadRequest" + "403": + description: Forbidden + +components: + responses: + ### Errors + BadRequest: + description: 400 Bad request + content: + application/json: + schema: + properties: + detail: + type: string + status: + type: number + default: 400 + title: + type: string + default: Bad request + type: + type: string + default: about:blank + NotFound: + description: 404 Not found + content: + application/json: + schema: + type: string + ServerError: + description: Server error + + ### Methods + PublicKey: + description: Public key response + content: + application/json: + schema: + $ref: "#/components/schemas/PublicKey" + Version: + description: Respond with current version + content: + application/json: + schema: + type: object + properties: + version: + type: string + example: "0.0.0" + + requestBodies: + RewrapV2: + description: RewrapV2 request body + required: true + content: + application/json: + schema: + oneOf: + - type: object + required: + - clientPayloadSignature + - keyAccess + maxProperties: 5 + properties: + clientPayloadSignature: + $ref: "#/components/schemas/AuthToken" + keyAccess: + $ref: "#/components/schemas/KeyAccess" + policy: + $ref: "#/components/schemas/Policy" + algorithm: + $ref: "#/components/schemas/TDF_Algorithm" + - type: object + required: + - signedRequestToken + maxProperties: 1 + properties: + signedRequestToken: + $ref: "#/components/schemas/JWT" + UpsertV2: + description: Upsert request body + required: true + content: + application/json: + schema: + oneOf: + - type: object + required: + - keyAccess + - policy + maxProperties: 4 + properties: + keyAccess: + $ref: "#/components/schemas/KeyAccess" + policy: + $ref: "#/components/schemas/Policy" + - type: object + required: + - signedRequestToken + + schemas: + Algorithm: + title: The algorithm used to encrypt the ciphertext + type: string + enum: + - AES-256-GCM + Aliases: + title: Array of userIds + type: array + items: + $ref: "#/components/schemas/UserId" + AuthToken: + $ref: "#/components/schemas/JWT" + Ciphertext: + title: Encrypted object + type: string + EncryptedMetadata: + title: Metadata in encrypted format + type: string + Exp: + title: JWT expiration date + type: number + IV: + title: Initial vector used to encrypt the ciphertext + type: string + JWT: + title: JSON Web token + type: string + pattern: ^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$ + KeyAccess: + title: Key access object + type: object + required: + - type + - url + - protocol + properties: + encryptedMetadata: + $ref: "#/components/schemas/EncryptedMetadata" + policySyncOptions: + $ref: "#/components/schemas/Policy" + policyBinding: + $ref: "#/components/schemas/PolicyBinding" + protocol: + type: string + enum: + - kas + type: + type: string + enum: + - remote + - remoteWrapped + - wrapped + url: + type: string + wrappedKey: + $ref: "#/components/schemas/WrappedKey" + Policy: + title: Policy + type: string + PolicyBinding: + title: Policy binding + type: string + PolicySyncOptions: + title: Policy sync options + type: object + properties: + url: + type: string + PublicKey: + title: Public key + type: string + pattern: '-----BEGIN PUBLIC KEY-----(.|\s)*-----END PUBLIC KEY-----(\s)*' + UserId: + title: User id + type: string + WrappedKey: + title: Wrapped key + type: string + TDF_Algorithm: + description: String to define the type of algorithm the client performing the TDF operations. + type: string + example: "ec:secp256r1" diff --git a/api/kas/swagger.yaml b/api/kas/swagger.yaml deleted file mode 100644 index ac6d69f..0000000 --- a/api/kas/swagger.yaml +++ /dev/null @@ -1,142 +0,0 @@ -swagger: '2.0' -info: - description: This is a basic KAS implementation - version: 1.0.0 - title: KAS Service - termsOfService: 'https://www.virtru.com/terms-of-service/' - contact: - email: biscoe@virtru.com - license: - name: Apache 2.0 - url: 'http://www.apache.org/licenses/LICENSE-2.0.html' -host: api.virtru.com -tags: - - name: all - description: All KAS operations - externalDocs: - description: 'Find out more:' - url: 'https://tdf3.readme.io/' -schemes: - - https -paths: - /: - get: - tags: - - all - summary: Just gets the version number - description: Just returns the version of the running KAS - produces: - - application/json - responses: - '200': - description: A public key object - schema: - type: object - properties: - version: - type: string - example: '1.1.0' - description: 'Semver version number' - /kas_public_key: - post: - tags: - - all - summary: Get a kas's public key - description: Just returns the public key for the KAS - produces: - - application/json - responses: - '200': - description: A public key object - schema: - $ref: '#/definitions/publicKeyObject' - /rewrap: - post: - tags: - - all - summary: Perform rewrap - description: Takes entity, policy, key access object, and returns an entity wrapped key - consumes: - - application/json - produces: - - application/json - parameters: - - in: body - name: Rewrap request body - required: true - description: "A json object containing the following:" - schema: - $ref: '#/definitions/rewrapRequestObject' - - responses: - '200': - description: A public key object - schema: - $ref: '#/definitions/entityWrappedKey' - /upsert: - post: - tags: - - all - summary: Perform policy upsert - description: Takes entity, policy, key access object, and syncs the policy with the backend - consumes: - - application/json - produces: - - application/json - parameters: - - in: body - name: Rewrap request body - required: true - description: "A json object containing the following:" - schema: - $ref: '#/definitions/rewrapRequestObject' - - responses: - '200': - description: Returns an array of status messages from each of the KAS plugins -definitions: - publicKeyObject: - type: object - required: - - publicKey - properties: - publicKey: - type: string - example: 'Some public key string' - xml: - name: publicKeyObject - entityWrappedKey: - type: object - required: - - entityWrappedKey - properties: - entityWrappedKey: - type: string - example: '... some entity wrapped key ...' - xml: - name: entityWrappedKey - rewrapRequestObject: - type: object - required: - - entity - - keyAccess - - policy - - authToken - properties: - entity: - type: object - example: '{ entity object}' - keyAccess: - type: object - example: '{ Key Access object}' - policy: - type: object - example: '{ Policy Object }' - authToken: - type: string - example: 'An auth JWT' - xml: - name: entityWrappedKey -externalDocs: - description: 'Find out more about EAS, and TDF3.' - url: 'https://tdf3.readme.io/' \ No newline at end of file diff --git a/protocol/README.md b/protocol/README.md index 4c0772c..7be5f4b 100755 --- a/protocol/README.md +++ b/protocol/README.md @@ -7,20 +7,20 @@ 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 our 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 who use it as the upstream project for their RH-SSO product." Keycloak is open source Apache License 2.0 code. - * Any IdP software should work in this scenario provided it can execute some custom code on successful authentication that can: +* *OpenID Connect (OIDC) Identity Provider (IdP)* - This system could be any OIDC IdP software. Virtru 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* is our Keycloak-specific reference implementation of the above functionality. -* *Attribute Provider* (AP) - A web service that will receive requests from our OIDC IdP custom code (ex: Virtru Protocol Mapper) containing information about authenticated subjet and return our custom OIDC/OAuth claims in response. It is the responsibility of Attribute Provider to transform incoming 3rd party IdP claims/metadata to outgoing ABAC policy attributes. 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. + * *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. ## Workflow -The following sequence diagrams illustrate the workflow taken by the client to encrypt or decrypt TDF ciphertext. The canonical TDF architecture supports two modes of operation: _online mode_ and _offline mode_, which have distinct workflows as shown below. +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. _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. diff --git a/schema/AttributeObject.md b/schema/AttributeObject.md index c0c1c8a..3f37fbe 100644 --- a/schema/AttributeObject.md +++ b/schema/AttributeObject.md @@ -1,17 +1,27 @@ # Attribute Object ## Summary -An Attribute Object contains attribute information the TDF3 system uses to enforce access control. Attributes are used in both the [PolicyObject](PolicyObject.md) to define the attributes that a user "needs" to gain access in an ABAC sense, and in the [EntityObject](EntityObject.md) to assert the attributes that a user "has" to satisfy the ABAC needs. +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. -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 (https://example.com), the attribute name (classification), and the attribute value (topsecret). +Attributes that a subject (or actor, or entity) "has" are referred to as "subject attributes". -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. For policies that do not include attributes these values are extracted from a _default_ attribute. Every [EntityObject](EntityObject.md) to a user who may write attribute-free policies should include one and only one _default_ attribute. +Attributes that subjects "need" in order to access data are referred to as "object attributes". -The AttributeObject does not define how the attribute will be used. The KAS uses 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. +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. -## Version +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). -The current schema version is `1.1.0`. +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 @@ -22,15 +32,15 @@ The current schema version is `1.1.0`. "displayName": "classification", "pubKey": "pem encoded public key of the attribute", "kasUrl": "https://kas.example.com/", - "schemaVersion:": "x.y.z" + "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. |Yes| +|`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| -|`schemaVersion`|String|Version number of the AttributeObject schema.|No| +|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| diff --git a/schema/ClaimsAttributeObject.md b/schema/ClaimsAttributeObject.md deleted file mode 100644 index f971a13..0000000 --- a/schema/ClaimsAttributeObject.md +++ /dev/null @@ -1,36 +0,0 @@ -# Attribute Object - -## Summary -An Attribute Object contains attribute information the TDF system uses to enforce access control. 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 a subject "has" to satisfy the ABAC needs. - -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 (https://example.com), the attribute name (classification), and the attribute value (topsecret). - -The public key is used to wrap the object key or key splits on TDF file creation. On decrypt, the kasUrl defines where this key or key split can be rewrapped. For policies that do not include attributes these values are extracted from a _default_ attribute. Every [ClaimsObject](ClaimsObject.md) to a subject who may write attribute-free policies should include one and only one _default_ attribute. - -The AttributeObject does not define how the attribute will be used. The KAS uses 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. - -## Version - -The current schema version is `4.0.0`. - -## 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/", - "schemaVersion:": "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. |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| -|`schemaVersion`|String|Version number of the AttributeObject schema.|No| diff --git a/schema/ClaimsObject.md b/schema/ClaimsObject.md index 0282b22..55e4181 100755 --- a/schema/ClaimsObject.md +++ b/schema/ClaimsObject.md @@ -2,66 +2,57 @@ ## What is this? -The Claims Object is a JSON object used to ensure that TDF Clients +The Claims Object is a JSON object used to ensure that subjects attempting to decrypt an encrypted file under the Trusted Data Format -has all permissions required to do so. +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 an TDF Client wishes to decrypt a file, the following steps using +When a subject wishes to decrypt a file, the following steps using the Claims Object are made: -1. The client requests a Claims Object by first authenticating via the +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 authentication succeeds, a +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 JWT is +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 [ClaimsAttributes](ClaimsAttributeObject.md) to which -the TDF Client has access. - +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 JWT (containing the Claims Object) as a bearer token to the 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 JWT signature. + +- 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 { - "userId": "user@virtru.com", - "aliases": [], - "attributes": [ - { - "obj": {"attribute": "https://example.com/attr/Classification/value/S"}} - }, - { - "obj": {"attribute": "https://example.com/attr/COI/value/PRX"}} - } + "subject_attributes": [ + {"attribute": "https://example.com/attr/Classification/value/S", "displayName": "classification"}, + {"attribute": "https://example.com/attr/COI/value/PRX", "displayName": "category of intent"} ], - "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy18Efi6+3vSELpbK58gC\nA9vJxZtoRHR604yi707h6nzTsTSNUg5mNzt/nWswWzloIWCgA7EPNpJy9lYn4h1Z\n6LhxEgf0wFcaux0/C19dC6WRPd6 ... XzNO4J38CoFz/\nwwIDAQAB\n-----END PUBLIC KEY-----", - "schemaVersion:": "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?| |---|---|---|---| -|`userId`|String|An id used to identify the entity, such as email.|Yes| -|`aliases`|Array|`aliases` are not yet implemented, but will provide further flexibility by assigning additional aliases to a user. This can remain empty for the time being.|Yes| -|`attributes`|Array|An array of [Claims Attribute Object](ClaimsAttributeObject.md)s. At most one of these may be a _default_ ClaimsAttributeObject.|Yes| -|`attributes.obj`|String|An [Claims Attribute Object](ClaimsAttributeObject.md)).|Yes| -|`publicKey`|String|The TDF Client's public key, in a PEM-encoded format.|Yes| -|`signerPublicKey`|String|A second public key used for signing KAS requests, in a PEM-encoded format. When using TDF with elliptic curve cryptography, the public key may use ECDH and the signing key ECDSA.|Optional, depends on choice of algorithm| -|`schemaVersion`|String|Version number of the Claims Object schema.|No| - - -## Version - -The current schema version is `4.0.0`. +|`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/schema/EntityObject.md b/schema/EntityObject.md deleted file mode 100755 index 270a517..0000000 --- a/schema/EntityObject.md +++ /dev/null @@ -1,50 +0,0 @@ -# Entity Object - -## What is this? - -The Entity Object is a JSON object used to ensure that individuals (entities) attempting to decrypt an encrypted file under the Trusted Data Format has all permissions required to do so. - -## How does it work? - -When an entity wishes to decrypt a file, the following steps using the Entity Object are made: - -1. The client requests an Entity Object from the EAS (Entity Attribute Service). The EAS processes this request by first authenticating the entity, and if that entity has successfully authenticated, creates and signs a valid Entity Object which is then returned to the client. This Entity Object contains [Attributes](AttributeObject.md) to which the entity has access. - -2. The client requests a decrypt from the Key Access Server (KAS) and in the process passes this Entity Object to it. The KAS ensures that the requestor has the correct permissions to access the contents of the file, by examining the validity of the Entity Object's signature, and if the entity has all the required Attributes and is on the [Policy Object](PolicyObject.md). If all of this has been met with success, the KAS will permit a decrypt of the file. - - -## Example - -```javascript -{ - "userId": "user@virtru.com", - "aliases": [], - "attributes": [ - { - "jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJodHR..." - }, - { - "jwt": "eyJhbGciOiJSUzI1NiIsInR5cCI6IPuQedtw5mNsJ0uDK4UdCChw..." - } - ], - "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy18Efi6+3vSELpbK58gC\nA9vJxZtoRHR604yi707h6nzTsTSNUg5mNzt/nWswWzloIWCgA7EPNpJy9lYn4h1Z\n6LhxEgf0wFcaux0/C19dC6WRPd6 ... XzNO4J38CoFz/\nwwIDAQAB\n-----END PUBLIC KEY-----", - "cert": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJ1c2...", - "schemaVersion:": "x.y.z" -} -``` - -|Parameter|Type|Description|Required?| -|---|---|---|---| -|`userId`|String|An id used to identify the entity, such as email, that will be used to authenticate against the EAS.|Yes| -|`aliases`|Array|`aliases` are not yet implemented, but will provide further flexibility by assigning additional aliases to a user. This can remain empty for the time being.|Yes| -|`attributes`|Array|An array of signed [Attribute Object](AttributeObject.md)s. At most one of these may be a _default_ AttributeObject.|Yes| -|`attributes.jwt`|String|An [Attribute Object](AttributeObject.md) that has been signed with the EAS private key as a [JWT](https://jwt.io/).|Yes| -|`publicKey`|String|The entity's public key, in a PEM-encoded format.|Yes| -|`signerPublicKey`|String|A second public key used for signing KAS requests, in a PEM-encoded format. When using TDF3 with elliptic curve cryptography, the public key may use ECDH and the signing key ECDSA.|Optional, depends on choice of algorithm| -|`cert`|String|The [Entity Object](EntityObject.md) contents (without `cert`) that has been signed with the EAS private key, as a [JWT](https://jwt.io/). The KAS uses this field to validate the authenticity of the Entity Object. |Yes| -|`schemaVersion`|String|Version number of the Entity Object schema.|No| - - -## Version - -The current schema version is `1.1.1`. diff --git a/schema/KeyAccessObject.md b/schema/KeyAccessObject.md index ff96da9..ace73b8 100755 --- a/schema/KeyAccessObject.md +++ b/schema/KeyAccessObject.md @@ -3,10 +3,6 @@ ## 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. -## Version - -The current schema version is `1.0.0`. - ## Example" ```javascript @@ -20,7 +16,7 @@ The current schema version is `1.0.0`. "hash": "BzmgoIxZzMmIF42qzbdD4Rw30GtdaRSQL2Xlfms1OPs=" }, "encryptedMetadata": "ZoJTNW24UMhnXIif0mSnqLVCU=", - "schemaVersion:": "x.y.z" + "tdf_spec_version:": "x.y.z" } ``` @@ -38,7 +34,6 @@ The current schema version is `1.0.0`. |`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| -|`schemaVersion`|String|Version number of the KeyAccessObject schema.|No| - +|`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 22fee0f..5b64ad5 100755 --- a/schema/PolicyObject.md +++ b/schema/PolicyObject.md @@ -1,15 +1,10 @@ # 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 entity object so that the KAS may make an access decision. +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). -## Version - -The current schema version is `1.0.0`. - ## Example ```javascript @@ -19,7 +14,7 @@ The current schema version is `1.0.0`. "dataAttributes": [], "dissem": ["user-id@domain.com"] }, -"schemaVersion:": "x.y.z" +"tdf_spec_version:": "x.y.z" } ``` @@ -29,7 +24,6 @@ The current schema version is `1.0.0`. |---|---|---| |`uuid`|String|A unique [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) for the TDF's policy.| - ## body |Parameter|Type|Description|Required?| @@ -37,10 +31,9 @@ The current schema version is `1.0.0`. |`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| -|`schemaVersion`|String|Version number of the PolicyObject schema.|No| -## schemaVersion +## tdf_spec_version |Parameter|Type|Description|Required?| |---|---|---|---| -|`schemaVersion`|String|Version number of the PolicyObject schema.|No| +|`tdf_spec_version`|String|Semver version number of the TDF spec.|No| diff --git a/schema/README.md b/schema/README.md index 8b580db..b1d2fef 100644 --- a/schema/README.md +++ b/schema/README.md @@ -1,8 +1,14 @@ +# TDF Schemas + A TDF file consists of: -* Encrypted payload -* [manifest.json](manifest-json.md). +* Encrypted payload +* [manifest.json](manifest-json.md). The [TDF protocol](https://github.com/virtru/tdf3-spec/tree/master/protocol) also defines the following objects: -* 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) -* An [Entity Object](EntityObject.md) created by the [Entity Attribute Service](https://developer.virtru.com/docs/how-to-host-an-eas) (EAS) + +* 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 [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. diff --git a/schema/manifest-json.md b/schema/manifest-json.md index 47432e7..44f97ad 100755 --- a/schema/manifest-json.md +++ b/schema/manifest-json.md @@ -10,10 +10,6 @@ From the top level, the TDF manifest contains only two properties: `payload` and If you'd like to see a real manifest created using the TDF3 client, check it out [here](#authentic-manifest). -## Version - -The current schema version is `3.0.0`. - ## 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. @@ -24,7 +20,7 @@ The payload contains metadata required to decrypt the TDF's payload, including _ "protocol": "zip", "isEncrypted": true, "mimeType": "application/pdf", - "schemaVersion:": "x.y.z" + "tdf_spec_version:": "x.y.z" } ``` @@ -35,7 +31,7 @@ The payload contains metadata required to decrypt the TDF's payload, including _ |`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| -|`schemaVersion`|String|Version number of the manifest schema.|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.