Certificate templates
Generated from core/api/router.go. Edit the router, not this file.
| Method | Path | Who can call it |
|---|---|---|
GET | /api/v1/certificate-templates | Any authenticated user |
POST | /api/v1/certificate-templates | Admin |
GET | /api/v1/certificate-templates/:id | Any authenticated user |
PUT | /api/v1/certificate-templates/:id | Admin |
DELETE | /api/v1/certificate-templates/:id | Admin |
GET /api/v1/certificate-templates
| Who can call it | Any authenticated user |
| Handler | templateHandler.List |
| Display token | Readable by an unattended screen |
Writes are admin-only, where a policy is operator-writable. A policy can only ever refuse more than it did; a template also supplies values and decides whether the requester may set the subject, and that last one is the difference between a template and a way to get a certificate for somebody else's name.
Responses
| Status | Body |
|---|---|
200 | An object with data (CertificateTemplate[]), total |
500 | { "error": … } |
Example request
curl -X GET 'https://certpilot.example.com/api/v1/certificate-templates' \
-H 'Authorization: Bearer <token>'POST /api/v1/certificate-templates
| Who can call it | Admin |
| Handler | templateHandler.Create |
| Display token | Refused — not a viewer-safe GET |
Request body
TemplateInput is what a caller may set on a certificate template. Narrow, rather than binding store.CertificateTemplate. Binding the model is what let a caller choose a policy's identifier and assert when it was written, and it is the same mistake here with twenty-eight columns instead of eight. Identity, authorship, timestamps and the version counter are not the caller's to set. The binding tags carry the CHECK constraints migration 036 put on the table. Without them an unknown subject_mode reaches PostgreSQL and comes back as a raw SQLSTATE 23514, which tells an operator nothing about which value they should have sent.
| Field | Type | Description | |
|---|---|---|---|
slug | string | required | maximum 63 |
name | string | required | |
description | string | ||
is_enabled | boolean | IsEnabled is a pointer so omitting it leaves the column's default of true, rather than a Go zero value quietly creating every template disabled. | |
ca_account_id | string | required | |
ca_profile | string | ||
subject_mode | string | one of SUPPLIED, CONSTRAINED | |
subject_defaults | object | ||
common_name_rule | CommonNameRule | ||
san_rules | SANRules | ||
allowed_key_types | string[] | ||
rsa_min_bits | integer | minimum 0 | |
rsa_max_bits | integer | minimum 0 | |
ecdsa_curves | string[] | ||
csr_required | boolean | ||
key_custody_required | string | one of ANY, CERTPILOT, AGENT, EXTERNAL | |
validity_days | integer | minimum 0 | |
max_validity_days | integer | minimum 0 | |
renew_before_days | integer | minimum 1 | |
auto_renew | boolean | ||
require_metadata | string[] | ||
default_environment | string | ||
default_team | string | ||
default_tags | string[] | ||
key_usage | string[] | KeyUsage and ExtendedKeyUsage — see #31. Deliberately no binding vocabulary check here: which names are valid depends on the CA this template points at (selfsigned enforces the full x509 vocabulary; ACME and Vault refuse the field entirely), so validate checks it against the account rather than a static list. | |
extended_key_usage | string[] | ||
basic_constraints_ca | boolean | ||
extension_passthrough | string | one of NONE, LISTED, ALL | |
passthrough_oids | string[] | ||
conformance | string | Conformance — see #30. A pointer so omitting it on create can default by CA type (ENFORCE for a private CA, REPORT otherwise) rather than always falling back to the column's own REPORT default, which would make every new template against a CA this deployment controls silently unenforced until an operator noticed and changed it. — one of ENFORCE, REPORT |
Responses
| Status | Body |
|---|---|
201 | Created |
400 | { "error": … } |
500 | { "error": … } |
Example request
curl -X POST 'https://certpilot.example.com/api/v1/certificate-templates' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"slug": "<slug>",
"name": "<name>",
"ca_account_id": "<ca_account_id>",
"description": "<description>",
"is_enabled": false
}'GET /api/v1/certificate-templates/:id
| Who can call it | Any authenticated user |
| Handler | templateHandler.Get |
| Display token | Readable by an unattended screen |
Parameters
| Name | In | Default | |
|---|---|---|---|
id | path | required |
Responses
| Status | Body |
|---|---|
200 | Success |
404 | { "error": … } |
500 | { "error": … } · could not read the certificate template |
Example request
curl -X GET 'https://certpilot.example.com/api/v1/certificate-templates/<id>' \
-H 'Authorization: Bearer <token>'PUT /api/v1/certificate-templates/:id
| Who can call it | Admin |
| Handler | templateHandler.Update |
| Display token | Refused — not a viewer-safe GET |
Parameters
| Name | In | Default | |
|---|---|---|---|
id | path | required |
Request body
TemplateInput is what a caller may set on a certificate template. Narrow, rather than binding store.CertificateTemplate. Binding the model is what let a caller choose a policy's identifier and assert when it was written, and it is the same mistake here with twenty-eight columns instead of eight. Identity, authorship, timestamps and the version counter are not the caller's to set. The binding tags carry the CHECK constraints migration 036 put on the table. Without them an unknown subject_mode reaches PostgreSQL and comes back as a raw SQLSTATE 23514, which tells an operator nothing about which value they should have sent.
| Field | Type | Description | |
|---|---|---|---|
slug | string | required | maximum 63 |
name | string | required | |
description | string | ||
is_enabled | boolean | IsEnabled is a pointer so omitting it leaves the column's default of true, rather than a Go zero value quietly creating every template disabled. | |
ca_account_id | string | required | |
ca_profile | string | ||
subject_mode | string | one of SUPPLIED, CONSTRAINED | |
subject_defaults | object | ||
common_name_rule | CommonNameRule | ||
san_rules | SANRules | ||
allowed_key_types | string[] | ||
rsa_min_bits | integer | minimum 0 | |
rsa_max_bits | integer | minimum 0 | |
ecdsa_curves | string[] | ||
csr_required | boolean | ||
key_custody_required | string | one of ANY, CERTPILOT, AGENT, EXTERNAL | |
validity_days | integer | minimum 0 | |
max_validity_days | integer | minimum 0 | |
renew_before_days | integer | minimum 1 | |
auto_renew | boolean | ||
require_metadata | string[] | ||
default_environment | string | ||
default_team | string | ||
default_tags | string[] | ||
key_usage | string[] | KeyUsage and ExtendedKeyUsage — see #31. Deliberately no binding vocabulary check here: which names are valid depends on the CA this template points at (selfsigned enforces the full x509 vocabulary; ACME and Vault refuse the field entirely), so validate checks it against the account rather than a static list. | |
extended_key_usage | string[] | ||
basic_constraints_ca | boolean | ||
extension_passthrough | string | one of NONE, LISTED, ALL | |
passthrough_oids | string[] | ||
conformance | string | Conformance — see #30. A pointer so omitting it on create can default by CA type (ENFORCE for a private CA, REPORT otherwise) rather than always falling back to the column's own REPORT default, which would make every new template against a CA this deployment controls silently unenforced until an operator noticed and changed it. — one of ENFORCE, REPORT |
Responses
| Status | Body |
|---|---|
200 | Success |
400 | { "error": … } |
404 | { "error": … } |
500 | { "error": … } · could not read the certificate template |
Example request
curl -X PUT 'https://certpilot.example.com/api/v1/certificate-templates/<id>' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"slug": "<slug>",
"name": "<name>",
"ca_account_id": "<ca_account_id>",
"description": "<description>",
"is_enabled": false
}'DELETE /api/v1/certificate-templates/:id
| Who can call it | Admin |
| Handler | templateHandler.Delete |
| Display token | Refused — not a viewer-safe GET |
Parameters
| Name | In | Default | |
|---|---|---|---|
id | path | required |
Responses
| Status | Body |
|---|---|
200 | An object with message (string) |
404 | { "error": … } |
409 | { "error": … } |
500 | { "error": … } · could not read the certificate template |
Example request
curl -X DELETE 'https://certpilot.example.com/api/v1/certificate-templates/<id>' \
-H 'Authorization: Bearer <token>'