Enrollment over secure transport
Overview
This API is based on the Device Configuration API framework. For guidance on how to use these APIs, please refer to Device Configuration APIs.
The VAPIX® Enrollment over secure transport API makes it possible to configure the device for automatic certificate enrollment. An EST profile can either be set in one call or patched to change its configuration.
Bootstrap distribution of CA certificates
During certificate enrollment, the device acts as an EST client and connects to an EST server, the enrollment endpoint operated by the certificate authority. The /cacerts operation is the client's request for the CA certificates it should trust.
CA certificates returned by the server in response to the /cacerts operation are added to the device's trust store automatically. No out-of-band verification of these certificates is performed.
This creates a bootstrap trust problem: on the very first connection, the device has no way to distinguish a legitimate EST server from an impostor. Whichever server it reaches will have its CA certificates installed and trusted from that point onward. An attacker who can intercept or redirect that initial request can establish themselves as a trusted certificate authority for the device.
Precautions should therefore be taken when configuring the server for certificate issuance:
- Pre-configure the device with the EST server's root certificate. This is the strongest option, as it removes the bootstrap problem entirely. The device can authenticate the server before trusting anything it sends.
- If pre-configuration is not possible, secure the server's DNS records with DNSSEC. This does not authenticate the server itself, but it prevents an attacker from redirecting the device to a different host through DNS manipulation.
Use cases
Set an EST profile
Add a new EST profile to the profile list. The certificate enrollment process starts when the minimal required settings are present.
Example:
- curl
- HTTP
curl --request POST \
--anyauth \
--user "<username>:<password>" \
--header "Content-Type: application/json" \
"http://<servername>/config/rest/cert-est/v1/profiles" \
--data '{
"data": {
"caCertificates": [
"root-cert-GlobalSign",
"inter-cert-GlobalSign"
],
"certificate": "client_cert",
"id": "EST Profile",
"server": "192.168.0.1:443/.well-known/est",
"subject": {
"cn": "My EST Client"
}
}
}'
POST /config/rest/cert-est/v1/profiles
Host: <servername>
Content-Type: application/json
{
"data": {
"caCertificates": [
"root-cert-GlobalSign",
"inter-cert-GlobalSign"
],
"certificate": "client_cert",
"id": "EST Profile",
"server": "192.168.0.1:443/.well-known/est",
"subject": {
"cn": "My EST Client"
}
}
}
201 Created
Content-Type: application/json
{
"status": "success",
"data": {
"caCertificates": [
"root-cert-GlobalSign",
"inter-cert-GlobalSign"
],
"certificate": "client_cert",
"id": "EST Profile",
"server": "192.168.0.1:443/.well-known/est",
"services": null,
"subject": {
"cn": "My EST Client"
},
"subjectAlternativeNames": null
}
}
Enrollment
To trigger enrollment, set a valid server URL, the name of the client certificate to authenticate with the server and the CA certificates needed to validate the certificate presented by the server to establish a TLS connection.
Delete an EST profile
Specify the EST profile to delete it.
- curl
- HTTP
curl --request DELETE \
--anyauth \
--user "<username>:<password>" \
--header "Content-Type: application/json" \
"http://<servername>/config/rest/cert-est/v1/profiles/EST Profile"
DELETE /config/rest/cert-est/v1/profiles/EST Profile
Host: <servername>
Content-Type: application/json
200 OK
Content-Type: application/json
{
"status": "success"
}
Set EST server
Specify the hostname of the server that enrolls new certificates.
The hostname can be either the IP or DNS of the server preceding the path, followed by a port number.
Examples of valid values:
"127.0.0.1""www.example.com:8443"
Example:
- curl
- HTTP
curl --request PATCH \
--anyauth \
--user "<username>:<password>" \
--header "Content-Type: application/json" \
"http://<servername>/config/rest/cert-est/v1/profiles/EST Profile/server" \
--data '{
"data": "www.example.com:8443"
}'
PATCH /config/rest/cert-est/v1/profiles/EST Profile/server
Host: <servername>
Content-Type: application/json
{
"data": "www.example.com:8443"
}
200 OK
Content-Type: application/json
{
"status": "success"
}
Set EST server CA certificates
Configure one or more CA certificates that the device will use to authenticate the EST server.
During enrollment, the device and the EST server perform mutual TLS authentication: the server verifies the device's identity, and the device verifies the server's. These certificates form the trust anchor for the second half of that exchange — the device accepts the server's TLS certificate only if it chains to one of the CA certificates configured here.
Obtain these certificates from the certificate authority that operates your EST server. In most deployments this is the root CA certificate of the issuing hierarchy, though an intermediate can be used if the server's certificate chains to it.
Configuring certificates here is the recommended alternative to allowing the device to accept CA certificates automatically via the /cacerts operation, which offers no protection against an impostor server on first connection.
Examples of valid values:
[ "EST server root CA" ]
Example:
- curl
- HTTP
curl --request PATCH \
--anyauth \
--user "<username>:<password>" \
--header "Content-Type: application/json" \
"http://<servername>/config/rest/cert-est/v1/profiles/EST Profile" \
--data '{
"data": {
"caCertificates": [
"root-cert-GlobalSign",
"inter-cert-GlobalSign"
]
}
}'
PATCH /config/rest/cert-est/v1/profiles/EST Profile
Host: <servername>
Content-Type: application/json
{
"data": {
"caCertificates": [
"root-cert-GlobalSign",
"inter-cert-GlobalSign"
]
}
}
200 OK
Content-Type: application/json
{
"status": "success"
}
Set client certificate
Set the certificate that is required to authenticate the client to the EST server.
Examples of valid values:
- "Device ID Certificate"
Example:
- curl
- HTTP
curl --request PATCH \
--anyauth \
--user "<username>:<password>" \
--header "Content-Type: application/json" \
"http://<servername>/config/rest/cert-est/v1/profiles/EST Profile" \
--data '{
"data": {
"certificate": "client_cert"
}
}'
PATCH /config/rest/cert-est/v1/profiles/EST Profile
Host: <servername>
Content-Type: application/json
{
"data": {
"certificate": "client_cert"
}
}
200 OK
Content-Type: application/json
{
"status": "success"
}
Set subject field of CSR
Set the X509 Subject used by the CSR when it is sent to the EST server during enroll and re-enroll.
The following Subject attributes are supported:
- Common Name
If not configured, the Common Name will default to <hostname>.
Example:
- curl
- HTTP
curl --request PATCH \
--anyauth \
--user "<username>:<password>" \
--header "Content-Type: application/json" \
"http://<servername>/config/rest/cert-est/v1/profiles/EST Profile/subject" \
--data '{
"data": {
"cn": "Common Name of certificate"
}
}'
PATCH /config/rest/cert-est/v1/profiles/EST Profile/subject
Host: <servername>
Content-Type: application/json
{
"data": {
"cn": "Common Name of certificate"
}
}
200 OK
Content-Type: application/json
{
"status": "success"
}
Set Subject Alternative Names of CSR
Set the SAN field used by the CSR when it is sent to the EST server during enroll and re-enroll.
Valid SAN values are IP addresses and domain names, each prefixed with the corresponding type.
Examples of valid values:
- "DNS:example.org"
- "IP:127.0.0.1"
If not configured, SAN will default to [DNS:<hostname>].
Example:
- curl
- HTTP
curl --request PATCH \
--anyauth \
--user "<username>:<password>" \
--header "Content-Type: application/json" \
"http://<servername>/config/rest/cert-est/v1/profiles/EST Profile" \
--data '{
"data": {
"subjectAlternativeNames": [
"IP:127.0.0.1"
]
}
}'
PATCH /config/rest/cert-est/v1/profiles/EST Profile
Host: <servername>
Content-Type: application/json
{
"data": {
"subjectAlternativeNames": [
"IP:127.0.0.1"
]
}
}
200 OK
Content-Type: application/json
{
"status": "success"
}
Services to assign enrolled certificate to
Set one or more services that will use the EST enrolled certificate.
The valid values of supported services is returned in the supportedServices properties.
Examples of valid values:
- 'WEBSERVER': The web server (HTTPS).
- 'NETAUTH': The 802.1X network authentication client.
- 'MQTT': The MQTT client service.
- 'RTSPS': The video streaming service (RTSP over TLS).
Error events
Error events are stateless events that are reported if the EST client fails. They are specified using the 'TopicExpression' and 'MessageContent' parameters. The following examples will show you how to receive these error events over a WebSocket connection.
WebSocket connection are initiated with an HTTP handshake sequence before being upgraded. The endpoint ws(s)://<device>/vapix/ws-data-stream should be use with digest authentication.
Example of a WebSocket flow:
Client WS handshake request
GET /vapix/ws-data-stream?sources=events HTTP/1.1
Host: 192.168.0.90
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Authorization: Digest username="root", realm="AXIS_ACCC8EC43707",
nonce="JrMSij/TBQA=646b1c2c4c0a80a7feb4e34ef9e3422180924c37",
uri="/vapix/ws-data-stream?sources=events",
algorithm=MD5, response="683f06da91f927fa1772c42f16597
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: 1L91ICBqd8iwa0I0e6Wgzg==
Server handshake response
Successful handshake response
HTTP/1.1 101 Switching Protocols
Date: Tue, 02 Nov 2021 16:09:47 GMT
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: kZ1kuOZMJmrfKnY8FvL7Tjwb0iw=
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits=15
Failure handshake response
HTTP/1.1 401 Unauthorized
Date: Tue, 02 Nov 2021 16:09:47 GMT
Server: Apache/2.4.48 (Unix) OpenSSL/1.1.1l
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
WWW-Authenticate: Digest realm="AXIS_ACCC8EC43707",
nonce="5X26hdDPBQA=f1d9367d1b0699f406a95bbf79e35f6e08c5d3af",
algorithm=MD5, stale=true, qop="auth"
Content-Length: 381
Content-Type: text/html; charset=iso-8859-1
Select events to receive
When the client has established a successful connection, it needs to specify what error events it wants to receive. This is done by sending a configuration request.
Client sends a configuration request with event filters
{
"request": {
"apiVersion": "1.0",
"context": "Client defined request ID",
"method": "events:configure",
"params": {
"eventFilterList": [
{
"topicFilter": "tnsaxis:CertificateManagement/EST/Error"
}
]
}
},
"response": {
"apiVersion": "1.0",
"context": "Client defined request ID",
"method": "events:configure",
"data": {}
}
}
Error events
Error events are sent to the client as JSON requests. The client should not respond to these notification requests.
Event notification syntax
{
"apiVersion": "1.0",
"method": "events:notify",
"params": {
"notification": {
"topic": "tnsaxis:CertificateManagement/EST/Error",
"timestamp": 1785242798912,
"message": {
"source": {
"Profile": "EST Example"
},
"key": {},
"data": {
"ErrorCode": "3",
"Message": "Request Error : 60 : SSL peer certificate or SSH remote key was not OK"
}
}
}
}
}
| Parameter | Description |
|---|---|
apiVersion=<string> | The API version used for the request. |
method=<string> | The performed operation. This field will be set to "events:notify" |
params.notification=<JSON object> | 'Required'. Specifies the event notification details. |
params.notification.timestamp=<integer> | 'Optional'. Specifies the timestamp for the notification. |
params.notification.topic=<string> | 'Required'. Specifies the topic for the notification. |
params.notification.message=<JSON Object> | 'Required'. Specifies the notification message. |
params.notification.message.source.Profile=<string> | 'Required'. Specifies the profile that has failed. |
params.notification.message.key=<key-value pairs> | 'Optional'. Specifies the key of notification. |
params.notification.message.data=<key-value pairs> | 'Required'. Specifies the data of notification. |
params.notification.message.data.ErrorCode=<string> | 'Required'. Specifies the error code. |
params.notification.message.data.Message=<string> | 'Required'. Additional error information. |
Error codes
| Error Code | Description |
|---|---|
| 0 | Internal error during startup of EST client. |
| 1 | External error during test connection. |
| 2 | Internal error during EST client connection. |
| 3 | External error during EST client connection. |
| 4 | Internal error during EST client enrollment. |
| 5 | External error during EST client enrollment. |
| 6 | Internal error during EST client re-enrollment. |
| 7 | External error during EST client re-enrollment. |
API definition
Structure
cert-est.v1 (Root Entity)
├── supportedServices (Property)
├── profiles (Entity Collection)
├── caCertificates (Property)
├── certificate (Property)
├── id (Property)
├── server (Property)
├── services (Property)
├── status (Property)
├── subject (Property)
├── subjectAlternativeNames (Property)
Entities
cert-est.v1
- Description: EST root object
- Type:
Singleton - Operations
- GET
- Attributes
- Dynamic Support: No
Properties
supportedServices
- Description: List of the services that can have enrolled certificates assigned to it.
- Datatype: ServiceList
- Operations
- GET (Permissions: admin, operator, viewer)
- Attributes
- Nullable: No
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
Actions
This entity has no actions.
cert-est.v1.profiles
- Description: EST profiles.
- Type: Collection (Key Property: id)
- Operations
- GET
- SET
- ADD
- Required properties:
id - Optional properties:
server,caCertificates,certificate,subject,subjectAlternativeNames,services
- Required properties:
- REMOVE
- Attributes
- Dynamic Support: No
Properties
caCertificates
- Description: EST server CA certificates
- Datatype: CertificateList
- Operations
- GET
- SET
- Attributes
- Nullable: Yes
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
certificate
- Description: Existing certificate to base CSR on
- Datatype: Alias
- Operations
- GET
- SET
- Attributes
- Nullable: Yes
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
id
- Description: EST profile identifier.
- Datatype: Alias
- Operations
- GET
- SET
- Attributes
- Nullable: No
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
server
- Description: EST server hostname.
- Datatype:
string - Operations
- GET
- SET
- Attributes
- Nullable: Yes
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
services
- Description: Services to assign enrolled certificate to
- Datatype: ServiceList
- Operations
- GET
- SET
- Attributes
- Nullable: Yes
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
status
- Description: Status of the setup of the EST profile
- Datatype: Status
- Operations
- GET
- Attributes
- Nullable: No
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
subject
- Description: x509 subject of the enrolled certificate
- Datatype: Subject
- Operations
- GET
- SET
- Attributes
- Nullable: Yes
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
subjectAlternativeNames
- Description: Subject alternative names, each prefixed with either "IP:" or "DNS:", e.g. "DNS:example.org"
- Datatype: SubjectAltNameList
- Operations
- GET
- SET
- Attributes
- Nullable: Yes
- Dynamic Support: No / Dynamic Enum: No / Dynamic Range: No
Actions
This entity has no actions.
Data Types
Alias
- Description: Client-defined identifier
- Type:
string - Minimum Length: 1
- Maximum Length: 128
CertificateList
- Description: Certificates list
- Type:
array - Element type: Alias
- Null Value: No
CommonName
- Description: The Common Name is used to specify the fully qualified domain name (FQDN) of the server or the name of the individual or organization for which the certificate is issued.
- Type:
string - Minimum Length: 1
- Maximum Length: 64
Service
- Description: A service to configure with an EST enrolled certificate.
- Type:
string - Enum Values: "WEBSERVER", "NETAUTH", "MQTT", "RTSPS"
ServiceList
- Description: Service list
- Type:
array - Element type: Service
- Null Value: No
Status
- Description: The EST profiles status.
- Type:
string - Enum Values: "UNCONNECTED", "CONNECTED", "ENROLLED"
Return the current status of the EST client.
- 'UNCONNECTED': There is currently no connection with the server.
- 'CONNECTED': The connection with the EST server is working. CA certificates will be downloaded.
- 'ENROLLED': The EST client has received a certificate from the EST server. It will request to renew the certificate before it expires.
Subject
- Description: Subject of the CSR that will be sent to the EST server. Uses the default subject settings if left empty.
- Type:
complex - Fields
- cn
- Description: Common Name
- Type: CommonName
- Nullable: Yes / Gettable: Yes
- cn
SubjectAltNameList
- Description: Subject Alternative Name list
- Type:
array - Element type: SubjectAlternativeName
- Null Value: No
SubjectAlternativeName
- Description: The Subject Alternative Name is used to specify additional domain names and IP addresses for which the certificate is issued.
- Type:
string