- Assumptions
- Endpoints
- [API roots](#API roots)
- Collections
- [Collection details](#Collection details)
- Objects
- [Object details](#Object details)
- [Object blob](#Object blob)
- Pagination
- [Object media types](#Object media types)
- Filtering
- Sorting
- Entities
- [Generic](#Generic rules)
- [API root](#API root entity)
- [Collection](#Collection entity)
- [Object](#Object entity)
- Authentication
- Extendability
- TAXII should facilitate CTI content exchange without content type descrimination.
- TAXII spec should define the base on which products can innovate, meaning it must be clearly defined and extendable.
- Try not to reinvent the wheel, havily based on JSON API spec - http://jsonapi.org/
- Implementation of both server and client should be straightforward.
- The less ambiguity, the better.
- Idea is to have one endpoint that lists all TAXII API roots designed to cater to different target groups.
- Current TAXII 2.0 spec suggests usage of DNS record for advertising this endpoint.
Request:
GET <discovery-url>/
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": [
{
"id": 1,
"type": "api-roots",
"attributes": {
"title": "Trust Group 1",
"description": "Description of Trust Group 1 TAXII root",
"contact_details": "Contact information for Trust Group 1"
},
"auth": {
"required": false
},
"links": {
"self": "https://taxii.example.com/group-1/"
}
},
{
"id": 2,
"type": "api-roots",
"attributes": {
"title": "Trust Group 2",
"description": "Description of Trust Group 2 TAXII root",
"contact_details": "Contact information for Trust Group 2"
},
"auth": {
"required": true,
"methods": [
{"type": "http-basic"},
{"type": "jwt", "href": "https://taxii.example/jwt/tokens"}
]
},
"links": {
"self": "https://taxii.example.com/group-2/"
}
}
],
"links": {
"self": "https://taxii.example.com/"
}
}
- returns a list of existing collections
- contains collections' details as included objects
Request:
GET <api-root>/
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": {
"type": "api-roots",
"attributes": {
"title": "Trust Group 1",
"description": "Description of Trust Group 1 TAXII root",
"contact_details": "Contact information for Trust Group 1"
},
"relationships": {
"collections": {
"data": [
{
"type": "collections",
"id": 10
},
{
"type": "collections",
"id": 20
}
]
}
}
},
"included": [
{
"type": "collections",
"id": 10,
"attributes": {
"name": "High Value Indicator Collection",
"description": "This data collection is for collecting high value IOCs",
"media_types": [
"application/vnd.oasis.stix+json; version=2.0"
]
},
"links": {
"self": "https://taxii.example.com/group-1/10"
},
"meta": {
"can_read": true,
"can_write": false,
"objects_count": 923
}
},
{
"type": "collections",
"id": 20,
"attributes": {
"name": "Indicators from the past 24-hours",
"description": "This data collection is for collecting current IOCs",
"media_types": [
"application/vnd.oasis.stix+json; version=2.0"
]
},
"links": {
"self": "https://taxii.example.com/group-1/20"
},
"meta": {
"can_read": true,
"can_write": true,
"objects_count": 10
}
}
],
"links": {
"self": "https://taxii.example.com/group-1/"
}
}
- returns the details about a collection
- server MAY include
meta.objects_count
in the response. It is a calculated field. - server MAY include
meta.count
in an reference object. It is a calculated field.
Request:
GET <api-root>/<collection-id>
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"meta": {
"can_read": true,
"can_write": true,
"objects_count": 10
},
"data": {
"type": "collections",
"attributes": {
"name": "Indicators from the past 24-hours",
"description": "This data collection is for collecting current IOCs",
"contact_details": "Contact information for this collection in Trust Group 1",
"media_types": [
"application/vnd.oasis.stix+json; version=2.0"
]
}
},
"links": {
"self": "https://taxii.example.com/group-1/",
"objects": {
"href": "https://taxii.example.com/group-1/20/objects",
"meta": {
"count": 10
}
}
}
}
- returns a list of objects
Request:
GET <api-root>/<collection-id>/objects
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "https://taxii.example.com/group-1/20/objects"
},
"data": [
{
"type": "objects",
"id": "1",
"attributes": {
"media_type": "application/vnd.oasis.stix+json; version=2.0"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/1",
"data": "https://taxii.example.com/group-1/20/objects/1/data"
}
},
{
"type": "objects",
"id": "2",
"attributes": {
"media_type": "application/pdf"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/2",
"data": "https://taxii.example.com/group-1/20/objects/2/data"
}
}
]
}
- returns object details, including list of versions (pagination for it?)
- version link points to another ordinary object
- when new version of the object comes in (new version is pushed in place of an object with specific ID), object is replaced in a collection and old version is added to versions list of that object.
- may contain collections info as included referenced objects
Request:
GET <api-root>/<collection-id>/objects/1
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "https://taxii.example.com/group-1/20/objects/1"
},
"data": {
"type": "objects",
"id": "1",
"attributes": {
"media_type": "application/vnd.oasis.stix+json; version=2.0",
"created_at": "2017-02-25T10:10:10.000111"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/1",
"data": "https://taxii.example.com/group-1/20/objects/1/data"
},
"meta": {
"version": "2017-01-23T11:11:21.854236"
},
"relationships": {
"versions": {
"data": [
{
"type": "objects",
"id": 19,
"meta": {
"version": "2017-02-20T18:12:22.854236"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/19",
"data": "https://taxii.example.com/group-1/20/objects/19/data"
}
},
{
"type": "objects",
"id": 30,
"meta": {
"version": "2017-01-21T18:12:22.854236"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/30",
"data": "https://taxii.example.com/group-1/20/objects/30/data"
}
}
]
},
"collections": {
"data": [
{
"type": "collections",
"id": 10
},
{
"type": "collections",
"id": 20
}
]
}
}
}
}
- serves object body as a blob with some content type
Request:
GET <api-root>/<collection-id>/objects/2/data
Reponse:
HTTP/1.1 200 OK
Content-Type: application/pdf
... binary data ...
- JSON-API spec description
- all endpoints that return a list of entities support pagination
- this spec does not define how pagination should be implemented, it is up to a server
- if pagination is requested by client or enforced by server, response MUST contains:
links.next
link that points to next pagemeta.page
object with page details
- server MAY include
meta.page.total
counter in the response
Request:
GET <api-root>/<collection-id>/objects?page[limit]=2
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "https://taxii.example.com/group-1/20/objects?page[limit]=2",
"next": "https://taxii.example.com/group-1/20/objects?page[cursor]=U2VydmVyIGluZm8gcGFnZSAx"
},
"meta": {
"page": {
"offset": 10,
"limit": 2,
"total": 35
}
},
"data": [
{
"type": "objects",
"id": "1",
"attributes": {
"media_type": "application/vnd.oasis.stix+json; version=2.0"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/1",
"data": "https://taxii.example.com/group-1/20/objects/1/data"
}
},
{
"type": "objects",
"id": "2",
"attributes": {
"media_type": "application/pdf"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/2",
"data": "https://taxii.example.com/group-1/20/objects/2/data"
}
}
]
}
- Object's
media_type
value must be a string and a proper MIME type - Allows low and high granularity. Examples:
application/pdf
application/vnd.oasis.stix+json; version=2.0
application/vnd.oasis.stix+json; version=2.0; subtype=indicator
application/vnd.oasis.stix+json; version=2.0; subtype=ttp
application/vnd.oasis.stix+xml; version=1.1.1
application/json; producer=eclecticiq
- all endpoints that return a list of entities support filtering (all fiels or predefined set?)
- Filtering parameter is defined as
filter[<field_name>]=<value>
.- The condition for each filter value MUST be EQUALS unless it is prefixed with:
>
(U+003E GREATER-THAN SIGN, ">"), in which case condition MUST be GREATER THAN.<
(U+003C LESS-THAN SIGN, "<"), in which case condition MUST be LESS THAN.>=
(U+003E GREATER-THAN SIGN, ">" and U+003D EQUALS-SIGN, “=”), in which case condition MUST be GREATER THAN OR EQUALS.<=
(U+003C LESS-THAN SIGN, ">" and U+003D EQUALS-SIGN, “=”), in which case condition MUST be LESS THAN OR EQUALS.
- Match MAY contain one value or multiple comma-separated values. If parameter contains multiple comma-separated (U+002C COMMA, “,”) values, these conditions MUST be joined with OR logical operator.
- One of more filters MAY be specified. If more than one filters specified, they are joined with AND logical operator.
- The condition for each filter value MUST be EQUALS unless it is prefixed with:
- if filtering is requested by client, response MUST contain:
meta.filters
list with all specified filters
Request:
GET <api-root>/<collection-id>/objects?filter[created_at]=<=2012-10-10&filter[media_type]=application%2Fvnd.oasis.stix%2Bjson%3B+version%3D2.0
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "https://taxii.example.com/group-1/20/objects/?filter[created_at]=<=2012-10-10&filter[media_type]=application%2Fvnd.oasis.stix%2Bjson%3B+version%3D2.0"
},
"meta": {
"filters": [
{"field": "created_at", "value": "<=2012-10-10"},
{"field": "media_type", "value": "application/vnd.oasis.stix+json; version=2.0"}
]
},
"data": [
{
"type": "objects",
"id": "1",
"attributes": {
"media_type": "application/vnd.oasis.stix+json; version=2.0",
"created_at": "2017-02-25T10:10:10.000111"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/1",
"data": "https://taxii.example.com/group-1/20/objects/1/data"
}
},
{
"type": "objects",
"id": "3",
"attributes": {
"media_type": "application/vnd.oasis.stix+json; version=2.0",
"created_at": "2017-02-21T11:11:11.000111"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/3",
"data": "https://taxii.example.com/group-1/20/objects/3/data"
}
}
]
}
- JSON API spec sorting
- TBA more details
- TAXII entities are Resource Objects
- TAXII entities can be represented as Resource Identifier Objects if their purpose in the response is to provide additional details.
- API root attributes are:
title
description
contact_details
- API root object MUST contain
auth
fieldauth
field's value is an objectauth.required
MUST be present and should betrue
orfalse
- if
auth.required
istrue
, object MUST havemethods
field with a listauth.methods
list contains objects representing supported authentication methods- supported authentication method object MUST have
type
string field and MAY have other fields (see example below) - see Authentication for more details.
API root entity:
{
"type": "api-roots",
"attributes": {
"title": "Trust Group 1",
"description": "Description of Trust Group 1 TAXII root",
"contact_details": "Contact information for Trust Group 1"
},
"auth": {
"required": true,
"methods": [
{"type": "http-basic"},
{"type": "jwt", "href": "https://taxii.example/jwt/tokens"}
]
}
}
meta
MAY containcan_read
,can_write
andobjects_count
fields.can_write
/can_read
fields are specific to current client session.objects_count
is a calculated field.
- Collection MUST contain a link to objects endpoint in
links
field - Server MAY return details of the collections that have
can_write=false
andcan_read=false
.
Collection entity:
{
"meta": {
"can_read": true,
"can_write": true,
"objects_count": 10
},
"data": {
"type": "collections",
"attributes": {
"name": "Indicators from the past 24-hours",
"description": "This data collection is for collecting current IOCs",
"contact_details": "Contact information for this collection in Trust Group 1",
"media_types": [
"application/vnd.oasis.stix+json; version=2.0"
]
}
},
"links": {
"self": "https://taxii.example.com/group-1/",
"objects": {
"href": "https://taxii.example.com/group-1/20/objects",
"meta": {
"count": 10
}
}
}
}
- Object entity MUST contain a link to specific blob endpoint in
links.data
{
"type": "objects",
"id": "1",
"attributes": {
"media_type": "application/vnd.oasis.stix+json; version=2.0",
"created_at": "2017-02-25T10:10:10.000111"
},
"links": {
"self": "https://taxii.example.com/group-1/20/objects/1",
"data": "https://taxii.example.com/group-1/20/objects/1/data"
}
}
- Authentication methods MAY differ per API root
- Supported authentication methods are advertised in API root object's
auth
field - Basic set of authentication methods (server MAY extend this with custom methods):
{"type": "http-basic"}
— HTTP Basic Authentication{"type": "jwt", "href": "JWT-AUTH-ENDPOINT-URL"}
— JWT based authentication
- If server advertises a particular authentication method, it MUST support it.
- (?) support custom extension based on JSON API extensions schema.
From the limited understanding: perhaps an easy way of showing what authorization is required to fetch a certain collection. So that without TRYING to authorize access, you know if you could. Especially useful in auto-discovery and such. e.g. I would like to see collections (if configured as such) i'm not authorized for. Catalogue vs access.