---
name: cumulocity-manage-trusted-certificates
description: "Upload the CA certificates that a tenant trusts for device authentication, list and update them, prove possession of their private key, and remove them. Use when the user wants to upload, list, update, verify, or remove the trusted CA certificates that devices authenticate with."
compatibility: "Requires network access to a Cumulocity tenant and the C8Y_BASEURL, C8Y_TENANT, C8Y_USER, and C8Y_PASSWORD environment variables."
---

# Manage trusted certificates

Source: https://cumulocity.com/docs/skills/device-management/manage-trusted-certificates/
Sector: Skills, Device management & connectivity
Release: Latest
Description: Upload the CA certificates that a tenant trusts for device authentication, list and update them, prove possession of their private key, and remove them.

## Before you start

Use these skills first:

- `cumulocity-authentication` skill: [Authenticate REST API requests](https://cumulocity.com/docs/skills/platform-administration/authentication/index.md)

Devices can authenticate with X.509 certificates instead of passwords. Cumulocity accepts a device certificate if the certificate authority (CA) that signed it is a trusted certificate of the tenant, and if that trusted certificate is enabled.

Upload the root certificate or an intermediate certificate of the chain that signs your device certificates. Do not upload the certificate of each device.

A trusted certificate must meet the following requirements:

* It is an X.509 certificate in PEM format.
* It is in version 3.
* It contains `BasicConstraints:[CA:true]`.
* It is still valid.
* It is not yet uploaded to Cumulocity.


> **Requirements:**
> ROLES & PERMISSIONS:
>
> * To add, update, and remove trusted certificates: ROLE_TENANT_MANAGEMENT_ADMIN or ROLE_TENANT_ADMIN
> * To read trusted certificates: ROLE_TENANT_MANAGEMENT_READ



The examples use `<tenant_id>` for the ID of your tenant and `<fingerprint>` for the fingerprint of a trusted certificate. The platform calculates the fingerprint when you upload the certificate. To find your tenant ID, send `GET /tenant/currentTenant` and read the `name` property.

### To upload a certificate {#to-upload-a-certificate}

Send an [Add a new certificate](https://cumulocity.com/api/core/#operation/postTrustedCertificateCollectionResource) request:

```http
POST /tenant/tenants/<tenant_id>/trusted-certificates
Content-Type: application/json
Accept: application/json

{
  "certInPemFormat": "-----BEGIN CERTIFICATE-----\nMIIDhzCCAm+gAwIBAgIUQ...\n-----END CERTIFICATE-----",
  "name": "My device CA",
  "status": "ENABLED",
  "autoRegistrationEnabled": false
}
```

The request has the following properties:

* `certInPemFormat`: The certificate in PEM format, with the line breaks escaped as `\n`.
* `name`: A name of your choice. Cumulocity does not use it.
* `status`: ENABLED or DISABLED. Devices with a certificate that is signed by a DISABLED certificate cannot connect.
* `autoRegistrationEnabled`: If `true`, the platform automatically registers new devices that connect with a certificate signed by this CA. This does not apply to devices that use the LWM2M protocol.

The platform returns HTTP 201 and the stored certificate. Note its `fingerprint` as `<fingerprint>`. The platform reads `issuer`, `subject`, `notBefore`, `notAfter`, `serialNumber`, and the other certificate details from the certificate. You cannot change them.

If the platform returns HTTP 409, the certificate is already uploaded. If it returns HTTP 422, the certificate does not meet the requirements.

### To upload several certificates at once {#to-upload-several-certificates-at-once}

Send an [Add multiple certificates](https://cumulocity.com/api/core/#operation/postTrustedCertificateCollectionResourceBulk) request with one entry per certificate:

```http
POST /tenant/tenants/<tenant_id>/trusted-certificates/bulk
Content-Type: application/json
Accept: application/json

{
  "certificates": [
    {
      "certInPemFormat": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
      "name": "Plant A CA",
      "status": "ENABLED",
      "autoRegistrationEnabled": false
    },
    {
      "certInPemFormat": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
      "name": "Plant B CA",
      "status": "ENABLED",
      "autoRegistrationEnabled": false
    }
  ]
}
```

The platform returns HTTP 201 and the stored certificates with their fingerprints. If one of the certificates is already uploaded, the platform returns HTTP 409. Remove that certificate from the list and send the request again.

### To list and read trusted certificates {#to-list-and-read-trusted-certificates}

To list all trusted certificates of the tenant, send a [Retrieve all stored certificates](https://cumulocity.com/api/core/#operation/getTrustedCertificateCollectionResource) request:

```http
GET /tenant/tenants/<tenant_id>/trusted-certificates?pageSize=2000
```

The `certificates` array of the response contains each certificate with its `fingerprint`, `name`, `status`, and validity.

To read one certificate, send a [Retrieve a stored certificate](https://cumulocity.com/api/core/#operation/getTrustedCertificateResource) request:

```http
GET /tenant/tenants/<tenant_id>/trusted-certificates/<fingerprint>
```

### To enable, disable, or rename a trusted certificate {#to-enable-disable-or-rename-a-trusted-certificate}

You can change the `name`, the `status`, and `autoRegistrationEnabled`. All other properties come from the certificate and cannot be changed.

Send an [Update a stored certificate](https://cumulocity.com/api/core/#operation/putTrustedCertificateResource) request:

```http
PUT /tenant/tenants/<tenant_id>/trusted-certificates/<fingerprint>
Content-Type: application/json
Accept: application/json

{
  "name": "My device CA (old)",
  "status": "DISABLED"
}
```

The platform returns HTTP 200 and the updated certificate. After you disable a certificate, devices with a certificate signed by this CA cannot connect anymore.

### To prove possession of the private key {#to-prove-possession-of-the-private-key}

The public part of a certificate is not secret, so anyone can upload it. With a proof of possession, you show that you own the private key of the certificate. See [Perform a proof of possession](https://cumulocity.com/docs/device-certificate-authentication/device-certificates/#perform-a-proof-of-possession) for the background.

1. Send a [Generate a verification code](https://cumulocity.com/api/core/#operation/postVerificationCodeTrustedCertificatesPopResource) request without a body:

    ```http
    POST /tenant/tenants/<tenant_id>/trusted-certificates-pop/<fingerprint>/verification-code
    Accept: application/json
    ```

    The response contains the code in `proofOfPossessionUnsignedVerificationCode` and its expiry time in `proofOfPossessionVerificationCodeUsableUntil`.

2. Save the code in a file, for example *verification_code.txt*, and sign it with the private key of the certificate:

    ```shell
    openssl dgst -sha256 -sign <private.key> verification_code.txt | openssl base64 -A
    ```

3. Send a [Provide the proof of possession](https://cumulocity.com/api/core/#operation/postTrustedCertificatePopResource) request with the signed code:

    ```http
    POST /tenant/tenants/<tenant_id>/trusted-certificates-pop/<fingerprint>/pop
    Content-Type: application/json
    Accept: application/json

    {
      "proofOfPossessionSignedVerificationCode": "<signed_verification_code>"
    }
    ```

The platform returns HTTP 200 and the certificate with `"proofOfPossessionValid": true`. If it returns HTTP 400, the signed code is wrong. Sign the current code again and send it again.

### To remove a trusted certificate {#to-remove-a-trusted-certificate}


> **Caution:**
> When you remove a trusted certificate, the platform closes the MQTT connections of all devices that use a certificate signed by this CA.



Send a [Remove a stored certificate](https://cumulocity.com/api/core/#operation/deleteTrustedCertificateResource) request:

```http
DELETE /tenant/tenants/<tenant_id>/trusted-certificates/<fingerprint>
```

The platform returns HTTP 204. If it returns HTTP 404, the certificate does not exist anymore.

## API reference

### Core API

Reference: https://cumulocity.com/api/core/

- [POST /tenant/tenants/{tenantId}/trusted-certificates](https://cumulocity.com/api/core/#operation/postTrustedCertificateCollectionResource): Add a new certificate
- [POST /tenant/tenants/{tenantId}/trusted-certificates/bulk](https://cumulocity.com/api/core/#operation/postTrustedCertificateCollectionResourceBulk): Add multiple certificates
- [GET /tenant/tenants/{tenantId}/trusted-certificates](https://cumulocity.com/api/core/#operation/getTrustedCertificateCollectionResource): Retrieve all stored certificates
- [GET /tenant/tenants/{tenantId}/trusted-certificates/{fingerprint}](https://cumulocity.com/api/core/#operation/getTrustedCertificateResource): Retrieve a stored certificate
- [PUT /tenant/tenants/{tenantId}/trusted-certificates/{fingerprint}](https://cumulocity.com/api/core/#operation/putTrustedCertificateResource): Update a stored certificate
- [POST /tenant/tenants/{tenantId}/trusted-certificates-pop/{fingerprint}/verification-code](https://cumulocity.com/api/core/#operation/postVerificationCodeTrustedCertificatesPopResource): Generate a verification code for the proof of possession
- [POST /tenant/tenants/{tenantId}/trusted-certificates-pop/{fingerprint}/pop](https://cumulocity.com/api/core/#operation/postTrustedCertificatePopResource): Provide the proof of possession
- [DELETE /tenant/tenants/{tenantId}/trusted-certificates/{fingerprint}](https://cumulocity.com/api/core/#operation/deleteTrustedCertificateResource): Remove a stored certificate

## Linked from the documentation

- [Managing trusted certificates](https://cumulocity.com/docs/device-certificate-authentication/managing-trusted-certificates/)
