Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/api.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: API checks

on:
push:
paths:
- 'docs/api/**'
pull_request:
paths:
- 'docs/api/**'

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Install OpenAPI spec validator
run: pip install openapi-spec-validator

- name: Check RATSD API
run: make -C docs/api check
31 changes: 31 additions & 0 deletions docs/api/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.DEFAULT_GOAL := help

# To validate an OpenAPI module, append the file name (without the .yaml
# extension) to the API variable. A "check_<YAML module>" target is
# automatically constructed and appended to the top level "check" goal.
API := ratsd

CMD := openapi-spec-validator

ifeq (, $(shell which $(CMD)))
$(error "No openapi-spec-validator in $(PATH); To install it, run: 'pip install openapi-spec-validator'")
endif

define OPENAPI_CHECK_template
.PHONY: check_$(1)

check_$(1): ; @printf ">>> $(1): " && $(CMD) $(1).yaml

HELP += "check_$(1): check only the $(1) template"
endef

$(foreach a,$(API),$(eval $(call OPENAPI_CHECK_template,$(a))))

.PHONY: check
check: $(foreach t,$(API),check_$(t))

.PHONY: help
help:
@printf "\nAvailable targets:\n"
@printf "\tcheck: run the OpenAPI spec validator on all API templates\n\n"
@printf "\t%s\n\n" $(HELP)
149 changes: 149 additions & 0 deletions docs/api/ratsd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
openapi: 3.0.0
info:
title: RATS Evidence Collection Daemon API
version: 0.0.1
tags: []
paths:
/ratsd/chares:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/ratsd/chares:
/ratsd/chalrsp:

Copy link
Contributor Author

@thomas-fossati thomas-fossati Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative is to use Greek in the URI (/ratsd/Χάρης) and the media type (application/vnd.veraison.Χάρης+json):

POST /ratsd/Χάρης HTTP/1.1
Host: host.example
Authorization: Bearer my.jwt.token
Accept: application/eat+jwt; eat_profile="tag:github.com,2024:veraison/ratsd"
Content-Type: application/vnd.veraison.Χάρης+json
Content-Length: 33

{
  "nonce": "MIDBNH28iioisjPy"
}

A fun conversation to have with IETF's Internationalization Directorate :-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we rename this to a more clear short version as chalrsp
which is more intuitive of what you intend to do.. Personally I struggled with what it means to be a chares?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not challengeReponse in full? ( camelCase or whatever notwithstanding?)

Is this interface only to be used for authentication tokens?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this interface only to be used for authentication tokens?

What do you mean by "authentication tokens"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I struggled with what it means to be a chares?

Chares of Lindos, the sculptor of one of the seven wonders of the world!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this interface only to be used for authentication tokens?

What do you mean by "authentication tokens"?

Just referring to an earlier statement. What is expected in the POST body and what is returned?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is expected in the POST body and what is returned?

The request body has an application/vnd.veraison.chares+json typed object:

{ "nonce": "base64url_encoded_nonce_" }

The request will also sport the auth token in the Authorization header:

Authorization: Bearer my.jwt.token

The response is a signed EAT with profile tag:github.com,2024:veraison/ratsd

post:
description: Challenge response API. Accepts a challenge and, upon success, generates the evidence in EAT w/ CMW format.
operationId: Ratsd_chares
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is chares other than the mythical ferryman? I’m trying to understand if 401 or 403 is the most appropriate error code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least for now, it seems sufficient to be successfully authenticated to request evidence using this challenge-response API. I cannot imagine a case where users who have provided an authentication token that checks out aren't also allowed to query this interface. In the future, we may add a 403 to handle such cases but for now 401 looks appropriate to me.

parameters:
- $ref: '#/components/parameters/ChaResRequestParameters.accept'
responses:
'200':
description: The request has succeeded.
content:
application/eat+jwt; eat_profile="tag:github.com,2024:veraison/ratsd":
schema:
$ref: '#/components/schemas/EAT'
'400':
description: The server could not understand the request due to invalid syntax.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/BadRequestError'
'401':
description: Access is unauthorized.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/UnauthorizedError'
requestBody:
required: true
content:
application/vnd.veraison.chares+json:
schema:
$ref: '#/components/schemas/ChaResRequest'
security:
- BearerAuth: []
components:
parameters:
ChaResRequestParameters.accept:
name: accept
in: header
required: false
schema:
type: string
schemas:
BadRequestError:
type: object
required:
- type
- title
- status
properties:
type:
type: string
enum:
- tag:github.com,2024:veraison/ratsd:error:invalidrequest
title:
type: string
enum:
- invalid request
status:
type: number
enum:
- 400
detail:
type: string
instance:
type: string
CMW:
type: object
required:
- typ
- val
properties:
typ:
type: string
enum:
- application/vnd.veraison.configfs-tsm+json
val:
type: string
format: base64url
ChaResRequest:
type: object
required:
- nonce
properties:
nonce:
type: string
format: base64url
EAT:
type: object
required:
- eat_profile
- nested-token
properties:
eat_profile:
type: string
enum:
- tag:github.com,2024:veraison/ratsd
nested-token:
$ref: '#/components/schemas/CMW'
ProblemDetails:
type: object
properties:
type:
type: string
title:
type: string
status:
type: integer
detail:
type: string
instance:
type: string
UnauthorizedError:
type: object
required:
- type
- title
- status
properties:
type:
type: string
enum:
- tag:github.com,2024:veraison/ratsd:error:unauthorized
title:
type: string
enum:
- access unauthorized
status:
type: number
enum:
- 401
detail:
type: string
instance:
type: string
Versions:
type: string
enum:
- 0.0.1
securitySchemes:
BearerAuth:
type: http
scheme: bearer

Loading