blob: e45207dbe4ba6ddc1b6410b152caaeb6db189593 [file] [log] [blame]
openapi: 3.0.1
info:
title: Eclipse Hono™ Device Registry API
description: |
This API defines how to manage *Tenants*, *Devices*, and *Credentials*.
It acts as a common basis which all Hono device registries should
implement.
## Required APIs
All operations, except the `tenants` resource are required. The tenant
management might be outside of the scope of the device registry and
managed by a higher level system. In this case all calls should simply
return `404`. However, if the `tenants` resource is implemented, then all
operations of it must be implemented.
## Security
This specification explicitly leaves out the part of authenticating and
authorizing users with the device registry. It is assumed that some form
of token exchange between the user agent and the backend service will
take place. Like for example HTTP basic authentication, or a bearer token.
## Code generation
This model is not optimized for generating code from it. Code generators
try to understand the model and then translate this into the require
programming language. Even if the there would be no bugs in the code
generators, that process would be already only be an approximation. So
this model does focus in the description of the API, and doesn't tweak
the specification in a way to please code generators.
contact:
name: Contact details
url: https://www.eclipse.org/hono/community/get-in-touch/
license:
name: EPL-2.0
url: https://www.eclipse.org/legal/epl-2.0/
version: 1.0.0
externalDocs:
description: Eclipse Hono™ web page
url: https://eclipse.org/hono
tags:
- name: tenants
description: Tenant Management (optional)
externalDocs:
description: Hono Multi-Tenancy
url: https://www.eclipse.org/hono/docs/concepts/tenancy/
- name: devices
description: Device registration
externalDocs:
description: Hono device identity
url: https://www.eclipse.org/hono/docs/concepts/device-identity/
- name: credentials
description: Device credentials
externalDocs:
description: Hono device identity
url: https://www.eclipse.org/hono/docs/concepts/device-identity/
servers:
- url: '{corsProxy}{server}/v1'
variables:
server:
default: http://hono.eclipse.org:28080
corsProxy:
default: https://cors-anywhere.herokuapp.com/
security:
- BearerAuth: []
- BasicAuth: []
paths:
# Tenant API
/tenants:
post:
tags:
- tenants
summary: Create new tenant with auto-generated ID
operationId: createTenant
requestBody:
description: New tenant information
content:
application/json:
schema:
$ref: '#/components/schemas/Tenant'
required: true
responses:
201:
$ref: '#/components/responses/Created'
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
/tenants/{tenantId}:
parameters:
- $ref: '#/components/parameters/tenantId'
post:
tags:
- tenants
summary: Create new tenant
operationId: createTenantWithId
requestBody:
description: New tenant registration
content:
application/json:
schema:
$ref: '#/components/schemas/Tenant'
required: true
responses:
201:
$ref: '#/components/responses/Created'
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
409:
$ref: '#/components/responses/AlreadyExists'
get:
tags:
- tenants
summary: Get tenant information
operationId: getTenant
responses:
200:
description: operation successful
content:
application/json:
schema:
$ref: '#/components/schemas/Tenant'
headers:
ETag:
description: Version of the resource
schema:
type: string
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- tenants
summary: Update tenant information
operationId: updateTenant
parameters:
- $ref: '#/components/parameters/resourceVersion'
requestBody:
description: Tenant information
content:
application/json:
schema:
$ref: '#/components/schemas/Tenant'
required: true
responses:
204:
$ref: '#/components/responses/Updated'
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
404:
$ref: '#/components/responses/NotFound'
412:
$ref: '#/components/responses/ResourceVersionMismatch'
delete:
tags:
- tenants
summary: Delete tenant
operationId: deleteTenant
parameters:
- $ref: '#/components/parameters/resourceVersion'
responses:
204:
$ref: '#/components/responses/Deleted'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
404:
$ref: '#/components/responses/NotFound'
412:
$ref: '#/components/responses/ResourceVersionMismatch'
# Device API
/devices/{tenantId}:
parameters:
- $ref: '#/components/parameters/tenantId'
post:
tags:
- devices
summary: Create new device registration with auto-generated ID
operationId: createDeviceRegistration
requestBody:
description: New device
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
required: true
responses:
201:
$ref: '#/components/responses/Created'
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
/devices/{tenantId}/{deviceId}:
parameters:
- $ref: '#/components/parameters/tenantId'
- $ref: '#/components/parameters/deviceId'
post:
tags:
- devices
summary: Create new device registration
operationId: createDeviceRegistrationWithId
requestBody:
description: New device
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
required: true
responses:
201:
$ref: '#/components/responses/Created'
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
409:
$ref: '#/components/responses/AlreadyExists'
get:
tags:
- devices
summary: Get device registration information
operationId: getRegistration
responses:
200:
description: operation successful
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
headers:
ETag:
description: Version of the resource
schema:
type: string
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- devices
summary: Update existing device registration
operationId: updateRegistration
parameters:
- $ref: '#/components/parameters/resourceVersion'
requestBody:
description: Updated device registration
content:
application/json:
schema:
$ref: '#/components/schemas/Device'
required: true
responses:
204:
$ref: '#/components/responses/Updated'
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
404:
$ref: '#/components/responses/NotFound'
412:
$ref: '#/components/responses/ResourceVersionMismatch'
delete:
tags:
- devices
summary: Delete device registration
operationId: deleteRegistration
parameters:
- $ref: '#/components/parameters/resourceVersion'
responses:
204:
$ref: '#/components/responses/Deleted'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
404:
$ref: '#/components/responses/NotFound'
412:
$ref: '#/components/responses/ResourceVersionMismatch'
/credentials/{tenantId}/{deviceId}:
parameters:
- $ref: '#/components/parameters/tenantId'
- $ref: '#/components/parameters/deviceId'
get:
tags:
- credentials
summary: Get credentials set of a device.
description: |
Get the credentials set of a device. As long as the device is
registered and the user has read access to it, this call should
never return "not found".
Depending on its implementation (or configuration), the device registry
can either return all credentials information including full secret details or
secret metadata along with the generated identifier (an `id` property).
The identifier can be used for the follow-up `update` operation).
operationId: getAllCredentials
responses:
200:
description: Operation successful
content:
application/json:
schema:
$ref: '#/components/schemas/CredentialsSet'
examples:
Full Credentials:
$ref: '#/components/examples/HashedPasswordExample'
Credentials Metadata:
$ref: '#/components/examples/MetaPasswordExample'
headers:
ETag:
description: Version of the resource
schema:
type: string
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- credentials
summary: Update credentials set for registered device
description: If the device registry is handling full secret details, the updated credential set
will be an exact match of the provided content. If it is using secret metadata,
data will be merged in based on the secret identities.
operationId: setAllCredentials
parameters:
- $ref: '#/components/parameters/resourceVersion'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CredentialsSet'
examples:
Hashed Password:
$ref: '#/components/examples/HashedPasswordExample'
Plain Password:
$ref: '#/components/examples/PlainPasswordExample'
required: true
responses:
204:
$ref: '#/components/responses/Updated'
400:
$ref: '#/components/responses/MalformedRequest'
401:
$ref: '#/components/responses/Unauthorized'
403:
$ref: '#/components/responses/NotAllowed'
404:
$ref: '#/components/responses/NotFound'
412:
$ref: '#/components/responses/ResourceVersionMismatch'
components:
schemas:
# Common schema
Error:
type: object
additionalProperties: true
required:
- error
properties:
"error":
type: string
description: A human readable error message of what went wrong.
DefaultProperties:
type: object
additionalProperties: true
description: Defaults for properties defined on the tenant and device level.
Extensions:
type: object
additionalProperties: true
description: Allows arbitrary properties as extension to the ones
specified by the Hono API.
# Tenant schema
Tenant:
type: object
additionalProperties: false
properties:
"enabled":
type: boolean
default: true
"ext":
$ref: '#/components/schemas/Extensions'
"adapters":
type: array
description: Only a single entry per type is allowed. If multiple entries for the same type are present it is handled as an error.
items:
$ref: '#/components/schemas/Adapter'
"defaults":
$ref: '#/components/schemas/DefaultProperties'
"minimum-message-size":
type: integer
default: 0
description: The minimum message size in bytes. If it is set
then the payload size of the telemetry, event and
command messages are calculated in accordance with
the configured value and then reported to the metrics.
"limits":
$ref: '#/components/schemas/ResourceLimit'
"trusted-ca":
$ref: '#/components/schemas/TrustedCA'
TrustedCA:
type: object
additionalProperties: false
required:
- "subject-dn"
properties:
"subject-dn":
type: string
description: The subject DN of the trusted root certificate in
the format defined by RFC 2253.
"public-key":
type: string
format: byte
description: The Base64 encoded binary DER encoding of the
trusted root certificate’s public key.
Either this property or `cert` must be set.
"cert":
type: string
format: byte
description: The Base64 encoded binary DER encoding of the
trusted root certificate. Either this property
or `public-key` must be set.
"algorithm":
type: string
description: The algorithm used for the public key of the CA.
If the `cert` property is used to provide an
X.509 certificate then the algorithm is determined
from the certificate and this property is ignored.
Otherwise, i.e. if the `public-key` property is
used, this property must be set to the algorithm
used, if other than the default.
default: RSA
example: EC
Adapter:
type: object
additionalProperties: true
required:
- type
properties:
"type":
type: string
"enabled":
type: boolean
default: false
"device-authentication-required":
type: boolean
default: true
"ext":
$ref: '#/components/schemas/Extensions'
ResourceLimit:
type: object
additionalProperties: false
properties:
"max-connections":
type: integer
default: -1
description: The maximum number of concurrent connections allowed
from devices of this tenant. The default value -1
indicates that no limit is set.
"ext":
$ref: '#/components/schemas/Extensions'
# Devices schema
Device:
type: object
additionalProperties: false
properties:
"enabled":
type: boolean
default: true
"defaults":
$ref: '#/components/schemas/DefaultProperties'
"via":
type: array
items:
type: string
description: The device IDs of the gateways this device is assigned to.
"ext":
$ref: '#/components/schemas/Extensions'
# Credentials
CredentialsSet:
type: array
description: A set of credentials. The entries in this list must be
unique by the composite key of `auth-id` and `type`.
items:
$ref: '#/components/schemas/TypedCredentials'
TypedCredentials:
additionalProperties: false
oneOf:
- $ref: '#/components/schemas/PasswordCredentials'
- $ref: '#/components/schemas/PSKCredentials'
- $ref: '#/components/schemas/X509CertificateCredentials'
discriminator:
propertyName: type
mapping:
"hashed-password": '#/components/schemas/PasswordCredentials'
"psk": '#/components/schemas/PSKCredentials'
"x509-cert": '#/components/schemas/X509CertificateCredentials'
CommonCredentials:
type: object
additionalProperties: false
required:
- auth-id
- type
properties:
"type":
type: string
"auth-id":
type: string
"enabled":
type: boolean
default: true
"ext":
$ref: '#/components/schemas/Extensions'
PasswordCredentials:
additionalProperties: false
allOf:
- $ref: '#/components/schemas/CommonCredentials'
- type: object
additionalProperties: false
properties:
"secrets":
type: array
items:
$ref: '#/components/schemas/PasswordSecret'
PSKCredentials:
additionalProperties: false
allOf:
- $ref: '#/components/schemas/CommonCredentials'
- type: object
additionalProperties: false
properties:
"secrets":
type: array
items:
$ref: '#/components/schemas/PSKSecret'
X509CertificateCredentials:
additionalProperties: false
allOf:
- $ref: '#/components/schemas/CommonCredentials'
- type: object
additionalProperties: false
properties:
"secrets":
type: array
items:
$ref: '#/components/schemas/X509CertificateSecret'
CommonSecret:
type: object
additionalProperties: false
properties:
"id":
type: string
description: The device registry can assign an identity to the secret.
This value can be used to update secrets based on their metadata.
"enabled":
type: boolean
default: true
"not-before":
type: string
format: date-time
"not-after":
type: string
format: date-time
"comment":
type: string
X509CertificateSecret:
additionalProperties: false
allOf:
- $ref: '#/components/schemas/CommonSecret'
PasswordSecret:
additionalProperties: false
allOf:
- $ref: '#/components/schemas/CommonSecret'
- type: object
additionalProperties: false
properties:
"hash-function":
type: string
example: sha-512
description: The name of the hash function used to create the password hash (defined in `pwd-hash` property).
If the password is defined using a `pwd-plain` property, this value will be ignored by the device registry.
This property should be empty when returning passwords from the device registry using only secret metadata.
In this case the id field must be set instead.
"pwd-hash":
type: string
format: byte
description: The password hash created using the `hash-function` and optional `salt` values.
If the password is defined using a `pwd-plain` property, this value will be ignored by the device registry.
This property should be empty when returning passwords from the device registry using only secret metadata.
In this case the id field must be set instead.
"salt":
type: string
format: byte
description: The Base64 encoding of the salt used in the password hash (defined in the `pwd-hash` property).
If the password is defined using a `pwd-plain` property, this value will be ignored by the device registry.
This property should be empty when returning passwords from the device registry using only secret metadata.
In this case the id field must be set instead.
"pwd-plain":
type: string
format: byte
description: The clear text value of the password to be hashed by the device registry.
If this property is specified, the device registry will ignore user-provided hash properties (`hash-function`, `pwd-hash` and `salt`).
This property should never be stored by the device registry.
This property should be empty when returning passwords from the device registry.
PSKSecret:
additionalProperties: false
allOf:
- $ref: '#/components/schemas/CommonSecret'
- type: object
additionalProperties: false
required:
- key
properties:
"key":
type: string
format: byte
parameters:
resourceVersion:
name: If-Match
in: header
description: The expected resource version
required: false
schema:
type: string
tenantId:
name: tenantId
in: path
description: The ID of the tenant
required: true
schema:
type: string
example: DEFAULT_TENANT
deviceId:
name: deviceId
in: path
description: The ID of the device
required: true
schema:
type: string
example: 4711
authId:
name: authId
in: path
description: The authentication ID of the device
required: true
schema:
type: string
example: sensor1
type:
name: type
in: path
description: The credentials type
required: true
schema:
type: string
example: sha-256
responses:
Unauthorized:
description: Authentication credentials are required, but missing.
headers:
"WWW-Authenticate":
schema:
type: string
Created:
description: Object created.
headers:
Location:
description: URL to the resource
schema:
type: string
format: uri
ETag:
description: The new version of the resource
schema:
type: string
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- id
properties:
id:
type: string
description: The ID of the created object
Updated:
description: Object updated.
headers:
ETag:
description: The new version of the resource
schema:
type: string
Deleted:
description: Object deleted.
NotFound:
description: |
Object not found. This may also be returned for some operations
if the user misses read access for the object.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotAllowed:
description: |
Operation not allowed. If the user does not have read access
for this object, then `404` will be returned instead.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
MalformedRequest:
description: Malformed request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
AlreadyExists:
description: |
Object already exists. If the user has no read access for
the existing object, then `403` should be returned instead.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
ResourceVersionMismatch:
description: |
Expected resource version does not match current.
This can only happen when the request header `If-Match`
was set.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
securitySchemes:
BearerAuth:
type: http
scheme: bearer
BasicAuth:
type: http
scheme: basic
examples:
HashedPasswordExample:
value:
auth-id: sensor1
type: hashed-password
secrets: [{
"not-after": "2027-12-24T19:00:00Z",
"pwd-hash": "AQIDBAUGBwg=",
"salt": "Mq7wFw==",
"hash-function": "sha-512"
}]
PlainPasswordExample:
value:
auth-id: sensor1
type: hashed-password
secrets: [{
"id": "349556ea-4902-47c7-beb0-1009ab693fb4",
"not-after": "2027-12-24T19:00:00Z",
"pwd-plain": "hono-secret"
}]
MetaPasswordExample:
value:
auth-id: sensor1
type: hashed-password
secrets: [{
"id": "349556ea-4902-47c7-beb0-1009ab693fb4",
"not-after": "2027-12-24T19:00:00Z",
"pwd-plain": "",
"pwd-hash": "",
"salt": "",
"hash-function": ""
}]