diff --git a/api/entitlement-api.yaml b/api/entitlement-api.yaml new file mode 100644 index 0000000..5acb53a --- /dev/null +++ b/api/entitlement-api.yaml @@ -0,0 +1,143 @@ +openapi: 3.0.2 +info: + title: FastAPI + version: 0.1.0 +paths: + /v1/claimsobject: + post: + summary: Request ClaimsObject + operationId: read_entity_attribute_relationship_v1_entity__entityId__claimsobject_post + requestBody: + $ref: "#/components/requestBodies/ClaimsRequest" + responses: + '200': + description: Successful Response + content: + application/json: + schema: {} + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + '404': + description: Entity Not Found Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + security: + - OAuth2AuthorizationCodeBearer: [] +components: + schemas: + AttributeObject: + title: AttributeObject + required: + - attribute + type: object + properties: + attribute: + title: Attribute + maxLength: 2083 + minLength: 1 + type: string + format: uri + example: + attribute: https://eas.local/attr/ClassificationUS/value/Unclassified + ClaimsObject: + title: ClaimsObject + required: + - subjects + - client_public_signing_key + type: object + properties: + entities: + title: Entities (min. 1) + type: array + items: + $ref: '#/components/schemas/EntitlementObject' + client_public_signing_key: + title: Requesting Entity Public Signing Key + type: string + tdf_spec_version: + title: Version of the TDF spec this object maps to (optional) + type: string + EntitlementObject: + title: EntitlementObject + required: + - entity_identifier + - entity_attributes + type: object + properties: + entity_identifier: + title: Entity Identifier + type: string + entity_attributes: + title: Entity Attributes + type: array + items: + $ref: '#/components/schemas/AttributeObject' + HTTPValidationError: + title: HTTPValidationError + type: object + properties: + detail: + title: Detail + type: array + items: + $ref: '#/components/schemas/ValidationError' + ValidationError: + title: ValidationError + required: + - loc + - msg + - type + type: object + properties: + loc: + title: Location + type: array + items: + type: string + msg: + title: Message + type: string + type: + title: Error Type + type: string + requestBodies: + ClaimsRequest: + description: Claims request body + required: true + content: + application/json: + schema: + oneOf: + - type: object + required: + - primary_subject_id + - secondary_entity_ids + - client_public_signing_key + maxProperties: 3 + properties: + primary_subject_id: + title: Primary entity ID entitlements are being fetched for (e.g. `sub` in JWT token) + type: string + secondary_entity_ids: + title: Secondary Entity Ids + description: Array of additional entities that EntitlementObjects should be fetched for. + type: array + items: + type: string + client_public_signing_key: + title: Requesting Client Public Signing Key + type: string + securitySchemes: + OAuth2AuthorizationCodeBearer: + type: oauth2 + flows: + authorizationCode: + scopes: {} + authorizationUrl: '' + tokenUrl: '' diff --git a/protocol/README.md b/protocol/README.md index 7be5f4b..e05c3a9 100755 --- a/protocol/README.md +++ b/protocol/README.md @@ -6,7 +6,8 @@ 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). +* *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. 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: @@ -15,8 +16,8 @@ The canonical architecture contains four major components. * 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. +* *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 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 (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 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 diff --git a/schema/AttributeObject.md b/schema/AttributeObject.md index 3f37fbe..e908fdd 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 TDF3 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/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.