Skip to content

Commit 1d63f11

Browse files
authored
feat: support client certificates (#126)
1 parent 0260f2f commit 1d63f11

6 files changed

+234
-0
lines changed

checkly.go

+56
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,62 @@ func (c *client) DeleteTriggerGroup(
13371337
return nil
13381338
}
13391339

1340+
func (c *client) CreateClientCertificate(
1341+
ctx context.Context,
1342+
cs ClientCertificate,
1343+
) (*ClientCertificate, error) {
1344+
data, err := json.Marshal(cs)
1345+
if err != nil {
1346+
return nil, err
1347+
}
1348+
status, res, err := c.apiCall(ctx, http.MethodPost, "client-certificates", data)
1349+
if err != nil {
1350+
return nil, err
1351+
}
1352+
if status != http.StatusCreated {
1353+
return nil, fmt.Errorf("unexpected response status: %d, res: %q", status, res)
1354+
}
1355+
var result ClientCertificate
1356+
err = json.NewDecoder(strings.NewReader(res)).Decode(&result)
1357+
if err != nil {
1358+
return nil, fmt.Errorf("decoding error for data %s: %v", res, err)
1359+
}
1360+
return &result, nil
1361+
}
1362+
1363+
func (c *client) GetClientCertificate(
1364+
ctx context.Context,
1365+
ID string,
1366+
) (*ClientCertificate, error) {
1367+
status, res, err := c.apiCall(ctx, http.MethodGet, fmt.Sprintf("client-certificates/%s", ID), nil)
1368+
if err != nil {
1369+
return nil, err
1370+
}
1371+
if status != http.StatusOK {
1372+
return nil, fmt.Errorf("unexpected response status %d: %q", status, res)
1373+
}
1374+
var result ClientCertificate
1375+
err = json.NewDecoder(strings.NewReader(res)).Decode(&result)
1376+
if err != nil {
1377+
return nil, fmt.Errorf("decoding error for data %q: %v", res, err)
1378+
}
1379+
return &result, nil
1380+
}
1381+
1382+
func (c *client) DeleteClientCertificate(
1383+
ctx context.Context,
1384+
ID string,
1385+
) error {
1386+
status, res, err := c.apiCall(ctx, http.MethodDelete, fmt.Sprintf("client-certificates/%s", ID), nil)
1387+
if err != nil {
1388+
return err
1389+
}
1390+
if status != http.StatusNoContent {
1391+
return fmt.Errorf("unexpected response status %d: %q", status, res)
1392+
}
1393+
return nil
1394+
}
1395+
13401396
func payloadFromAlertChannel(ac AlertChannel) map[string]interface{} {
13411397
payload := map[string]interface{}{
13421398
"id": ac.ID,

checkly_integration_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -379,3 +379,43 @@ func TestTCPCheckCRUD(t *testing.T) {
379379
t.Fatalf("failed to delete TCP check: %v", err)
380380
}
381381
}
382+
383+
func TestClientCertificateCRD(t *testing.T) {
384+
ctx := context.TODO()
385+
386+
client := setupClient(t)
387+
388+
pendingClientCertificate := checkly.ClientCertificate{
389+
Host: "*.acme.com",
390+
Certificate: "-----BEGIN CERTIFICATE-----\nMIICDzCCAbagAwIBAgIUMTZlfGA7WcD8e4/zt2MqxvEgQPYwCgYIKoZIzj0EAwIw\nVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhUb29udG93bjES\nMBAGA1UECgwJQWNtZSBJbmMuMREwDwYDVQQDDAhhY21lLmNvbTAeFw0yNTAzMDMw\nNTQ2NTJaFw00OTEwMjMwNTQ2NTJaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\nQTERMA8GA1UEBwwIVG9vbnRvd24xEjAQBgNVBAoMCUFjbWUgSW5jLjEXMBUGA1UE\nAwwOV2lsZSBFLiBDb3lvdGUxHDAaBgkqhkiG9w0BCQEWDXdpbGVAYWNtZS5jb20w\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATAjjDGsKFS1qgdNqziDZoD5hamTfdH\n0P+Ukk1RIue57QYVXhQSyNzcEz15kQnwYezEqfN+FtjtTwdk/CgnAELlo0IwQDAd\nBgNVHQ4EFgQU9C9CpZqM2WMrOs3vAYsc5GbjyzswHwYDVR0jBBgwFoAUnlOyzF/N\nK7YmKQegLdbdyIOCT/UwCgYIKoZIzj0EAwIDRwAwRAIgGgSnBymlH4MkZCVk5DYH\nPdnDo2Xf5uFi1Eyn2LTYP1MCIEtiGtsf0qYv6NzIPd5uTTZoB/8hPrAgM1QzWG4O\n3C/I\n-----END CERTIFICATE-----\n",
391+
PrivateKey: "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIH0MF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBA5yR3aqy8mZD2wQzp1\nFH2JAgIIADAMBggqhkiG9w0CCQUAMB0GCWCGSAFlAwQBKgQQA49YCnXvfJ2CsQsV\n9C5JJwSBkNkWunSlqyeVW6OFa/+OjlLArgTGvW5ul08qu/145O9PO4Nr2CXeK5N2\nuvHwkWGfD8IVke+sgZPUjLoHsJ4h4AnyxlNHpIxgOfm0CoXT7PTaFb//d5NC6XyB\nK7ZpBzIThGlbuS/b9wp4MPmSaJn5Fci+84VG7KYK5RxU0fcU0rGSBynrZw803wnO\nFjP7qaq5bw==\n-----END ENCRYPTED PRIVATE KEY-----\n",
392+
Passphrase: "secret password",
393+
TrustedCA: "-----BEGIN CERTIFICATE-----\nMIIB/jCCAaOgAwIBAgIUZzxdNpoDYXaNiIBsh0/s++I+ZOEwCgYIKoZIzj0EAwIw\nVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhUb29udG93bjES\nMBAGA1UECgwJQWNtZSBJbmMuMREwDwYDVQQDDAhhY21lLmNvbTAeFw0yNTAzMDMw\nNTQzMDZaFw0yNTA0MDIwNTQzMDZaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\nQTERMA8GA1UEBwwIVG9vbnRvd24xEjAQBgNVBAoMCUFjbWUgSW5jLjERMA8GA1UE\nAwwIYWNtZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARDH3KGK6Vsk1A4\nyGf9ItQIS3yuAOi0n0ihmPzIOOOEN0c758ETABeUdgH55bakdx6q5KYSxf4TuXsJ\n2nCihqVVo1MwUTAdBgNVHQ4EFgQUnlOyzF/NK7YmKQegLdbdyIOCT/UwHwYDVR0j\nBBgwFoAUnlOyzF/NK7YmKQegLdbdyIOCT/UwDwYDVR0TAQH/BAUwAwEB/zAKBggq\nhkjOPQQDAgNJADBGAiEA/cJ9jV8MQz4ypQsFvUatrnbxyHO0f+pJhf09pAk6Kj8C\nIQCkSbope5r0KlVdqBeFF8wCfE3plwpelve3jqVIz6MedQ==\n-----END CERTIFICATE-----\n",
394+
}
395+
396+
createdClientCertificate, err := client.CreateClientCertificate(ctx, pendingClientCertificate)
397+
if err != nil {
398+
t.Fatalf("failed to create client certificate: %v", err)
399+
}
400+
var didDelete bool
401+
defer func() {
402+
if !didDelete {
403+
_ = client.DeleteClientCertificate(ctx, createdClientCertificate.ID)
404+
}
405+
}()
406+
407+
readClientCertificate, err := client.GetClientCertificate(ctx, createdClientCertificate.ID)
408+
if err != nil {
409+
t.Fatalf("failed to get client certificate: %v", err)
410+
}
411+
412+
if !cmp.Equal(createdClientCertificate, readClientCertificate) {
413+
t.Error(cmp.Diff(createdClientCertificate, readClientCertificate, ignorePrivateLocationFields))
414+
}
415+
416+
didDelete = true
417+
err = client.DeleteClientCertificate(ctx, createdClientCertificate.ID)
418+
if err != nil {
419+
t.Fatalf("failed to delete client certificate: %v", err)
420+
}
421+
}

checkly_test.go

+79
Original file line numberDiff line numberDiff line change
@@ -1585,3 +1585,82 @@ func TestGetStaticIPs(t *testing.T) {
15851585
}
15861586
}
15871587
}
1588+
1589+
var ignoreClientCertificateFields = cmpopts.IgnoreFields(checkly.ClientCertificate{}, "ID", "Passphrase", "CreatedAt")
1590+
1591+
var testClientCertificate = checkly.ClientCertificate{
1592+
ID: "49a1d5df-b89a-4998-a469-b1358e282ea5",
1593+
Host: "*.acme.com",
1594+
Certificate: "-----BEGIN CERTIFICATE-----\nMIICDzCCAbagAwIBAgIUMTZlfGA7WcD8e4/zt2MqxvEgQPYwCgYIKoZIzj0EAwIw\nVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhUb29udG93bjES\nMBAGA1UECgwJQWNtZSBJbmMuMREwDwYDVQQDDAhhY21lLmNvbTAeFw0yNTAzMDMw\nNTQ2NTJaFw00OTEwMjMwNTQ2NTJaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\nQTERMA8GA1UEBwwIVG9vbnRvd24xEjAQBgNVBAoMCUFjbWUgSW5jLjEXMBUGA1UE\nAwwOV2lsZSBFLiBDb3lvdGUxHDAaBgkqhkiG9w0BCQEWDXdpbGVAYWNtZS5jb20w\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATAjjDGsKFS1qgdNqziDZoD5hamTfdH\n0P+Ukk1RIue57QYVXhQSyNzcEz15kQnwYezEqfN+FtjtTwdk/CgnAELlo0IwQDAd\nBgNVHQ4EFgQU9C9CpZqM2WMrOs3vAYsc5GbjyzswHwYDVR0jBBgwFoAUnlOyzF/N\nK7YmKQegLdbdyIOCT/UwCgYIKoZIzj0EAwIDRwAwRAIgGgSnBymlH4MkZCVk5DYH\nPdnDo2Xf5uFi1Eyn2LTYP1MCIEtiGtsf0qYv6NzIPd5uTTZoB/8hPrAgM1QzWG4O\n3C/I\n-----END CERTIFICATE-----\n",
1595+
PrivateKey: "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIH0MF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBA5yR3aqy8mZD2wQzp1\nFH2JAgIIADAMBggqhkiG9w0CCQUAMB0GCWCGSAFlAwQBKgQQA49YCnXvfJ2CsQsV\n9C5JJwSBkNkWunSlqyeVW6OFa/+OjlLArgTGvW5ul08qu/145O9PO4Nr2CXeK5N2\nuvHwkWGfD8IVke+sgZPUjLoHsJ4h4AnyxlNHpIxgOfm0CoXT7PTaFb//d5NC6XyB\nK7ZpBzIThGlbuS/b9wp4MPmSaJn5Fci+84VG7KYK5RxU0fcU0rGSBynrZw803wnO\nFjP7qaq5bw==\n-----END ENCRYPTED PRIVATE KEY-----\n",
1596+
Passphrase: "secret password",
1597+
TrustedCA: "-----BEGIN CERTIFICATE-----\nMIIB/jCCAaOgAwIBAgIUZzxdNpoDYXaNiIBsh0/s++I+ZOEwCgYIKoZIzj0EAwIw\nVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhUb29udG93bjES\nMBAGA1UECgwJQWNtZSBJbmMuMREwDwYDVQQDDAhhY21lLmNvbTAeFw0yNTAzMDMw\nNTQzMDZaFw0yNTA0MDIwNTQzMDZaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\nQTERMA8GA1UEBwwIVG9vbnRvd24xEjAQBgNVBAoMCUFjbWUgSW5jLjERMA8GA1UE\nAwwIYWNtZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARDH3KGK6Vsk1A4\nyGf9ItQIS3yuAOi0n0ihmPzIOOOEN0c758ETABeUdgH55bakdx6q5KYSxf4TuXsJ\n2nCihqVVo1MwUTAdBgNVHQ4EFgQUnlOyzF/NK7YmKQegLdbdyIOCT/UwHwYDVR0j\nBBgwFoAUnlOyzF/NK7YmKQegLdbdyIOCT/UwDwYDVR0TAQH/BAUwAwEB/zAKBggq\nhkjOPQQDAgNJADBGAiEA/cJ9jV8MQz4ypQsFvUatrnbxyHO0f+pJhf09pAk6Kj8C\nIQCkSbope5r0KlVdqBeFF8wCfE3plwpelve3jqVIz6MedQ==\n-----END CERTIFICATE-----\n",
1598+
}
1599+
1600+
func validateClientCertificate(t *testing.T, body []byte) {
1601+
var clientCertificate checkly.ClientCertificate
1602+
err := json.Unmarshal(body, &clientCertificate)
1603+
if err != nil {
1604+
t.Fatalf("decoding error for data %q: %v", body, err)
1605+
}
1606+
if !cmp.Equal(testClientCertificate, clientCertificate) {
1607+
t.Error(cmp.Diff(testClientCertificate, clientCertificate))
1608+
}
1609+
}
1610+
1611+
func TestCreateClientCertificate(t *testing.T) {
1612+
t.Parallel()
1613+
ts := cannedResponseServer(t,
1614+
http.MethodPost,
1615+
"/v1/client-certificates",
1616+
validateClientCertificate,
1617+
http.StatusCreated,
1618+
"CreateClientCertificate.json",
1619+
)
1620+
defer ts.Close()
1621+
client := checkly.NewClient(ts.URL, "dummy-key", ts.Client(), nil)
1622+
response, err := client.CreateClientCertificate(context.Background(), testClientCertificate)
1623+
if err != nil {
1624+
t.Error(err)
1625+
}
1626+
if !cmp.Equal(testClientCertificate, *response, ignoreClientCertificateFields) {
1627+
t.Error(cmp.Diff(testClientCertificate, *response, ignoreClientCertificateFields))
1628+
}
1629+
}
1630+
1631+
func TestGetClientCertificate(t *testing.T) {
1632+
t.Parallel()
1633+
ts := cannedResponseServer(t,
1634+
http.MethodGet,
1635+
fmt.Sprintf("/v1/client-certificates/%s", testClientCertificate.ID),
1636+
validateEmptyBody,
1637+
http.StatusOK,
1638+
"GetClientCertificate.json",
1639+
)
1640+
defer ts.Close()
1641+
client := checkly.NewClient(ts.URL, "dummy-key", ts.Client(), nil)
1642+
response, err := client.GetClientCertificate(context.Background(), testClientCertificate.ID)
1643+
if err != nil {
1644+
t.Error(err)
1645+
}
1646+
if !cmp.Equal(testClientCertificate, *response, ignoreClientCertificateFields) {
1647+
t.Error(cmp.Diff(testClientCertificate, *response, ignoreClientCertificateFields))
1648+
}
1649+
}
1650+
1651+
func TestDeleteClientCertificate(t *testing.T) {
1652+
t.Parallel()
1653+
ts := cannedResponseServer(t,
1654+
http.MethodDelete,
1655+
fmt.Sprintf("/v1/client-certificates/%s", testClientCertificate.ID),
1656+
validateEmptyBody,
1657+
http.StatusNoContent,
1658+
"Empty.json",
1659+
)
1660+
defer ts.Close()
1661+
client := checkly.NewClient(ts.URL, "dummy-key", ts.Client(), nil)
1662+
err := client.DeleteClientCertificate(context.Background(), testClientCertificate.ID)
1663+
if err != nil {
1664+
t.Error(err)
1665+
}
1666+
}

fixtures/CreateClientCertificate.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "49a1d5df-b89a-4998-a469-b1358e282ea5",
3+
"host": "*.acme.com",
4+
"cert": "-----BEGIN CERTIFICATE-----\nMIICDzCCAbagAwIBAgIUMTZlfGA7WcD8e4/zt2MqxvEgQPYwCgYIKoZIzj0EAwIw\nVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhUb29udG93bjES\nMBAGA1UECgwJQWNtZSBJbmMuMREwDwYDVQQDDAhhY21lLmNvbTAeFw0yNTAzMDMw\nNTQ2NTJaFw00OTEwMjMwNTQ2NTJaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\nQTERMA8GA1UEBwwIVG9vbnRvd24xEjAQBgNVBAoMCUFjbWUgSW5jLjEXMBUGA1UE\nAwwOV2lsZSBFLiBDb3lvdGUxHDAaBgkqhkiG9w0BCQEWDXdpbGVAYWNtZS5jb20w\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATAjjDGsKFS1qgdNqziDZoD5hamTfdH\n0P+Ukk1RIue57QYVXhQSyNzcEz15kQnwYezEqfN+FtjtTwdk/CgnAELlo0IwQDAd\nBgNVHQ4EFgQU9C9CpZqM2WMrOs3vAYsc5GbjyzswHwYDVR0jBBgwFoAUnlOyzF/N\nK7YmKQegLdbdyIOCT/UwCgYIKoZIzj0EAwIDRwAwRAIgGgSnBymlH4MkZCVk5DYH\nPdnDo2Xf5uFi1Eyn2LTYP1MCIEtiGtsf0qYv6NzIPd5uTTZoB/8hPrAgM1QzWG4O\n3C/I\n-----END CERTIFICATE-----\n",
5+
"key": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIH0MF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBA5yR3aqy8mZD2wQzp1\nFH2JAgIIADAMBggqhkiG9w0CCQUAMB0GCWCGSAFlAwQBKgQQA49YCnXvfJ2CsQsV\n9C5JJwSBkNkWunSlqyeVW6OFa/+OjlLArgTGvW5ul08qu/145O9PO4Nr2CXeK5N2\nuvHwkWGfD8IVke+sgZPUjLoHsJ4h4AnyxlNHpIxgOfm0CoXT7PTaFb//d5NC6XyB\nK7ZpBzIThGlbuS/b9wp4MPmSaJn5Fci+84VG7KYK5RxU0fcU0rGSBynrZw803wnO\nFjP7qaq5bw==\n-----END ENCRYPTED PRIVATE KEY-----\n",
6+
"ca": "-----BEGIN CERTIFICATE-----\nMIIB/jCCAaOgAwIBAgIUZzxdNpoDYXaNiIBsh0/s++I+ZOEwCgYIKoZIzj0EAwIw\nVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhUb29udG93bjES\nMBAGA1UECgwJQWNtZSBJbmMuMREwDwYDVQQDDAhhY21lLmNvbTAeFw0yNTAzMDMw\nNTQzMDZaFw0yNTA0MDIwNTQzMDZaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\nQTERMA8GA1UEBwwIVG9vbnRvd24xEjAQBgNVBAoMCUFjbWUgSW5jLjERMA8GA1UE\nAwwIYWNtZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARDH3KGK6Vsk1A4\nyGf9ItQIS3yuAOi0n0ihmPzIOOOEN0c758ETABeUdgH55bakdx6q5KYSxf4TuXsJ\n2nCihqVVo1MwUTAdBgNVHQ4EFgQUnlOyzF/NK7YmKQegLdbdyIOCT/UwHwYDVR0j\nBBgwFoAUnlOyzF/NK7YmKQegLdbdyIOCT/UwDwYDVR0TAQH/BAUwAwEB/zAKBggq\nhkjOPQQDAgNJADBGAiEA/cJ9jV8MQz4ypQsFvUatrnbxyHO0f+pJhf09pAk6Kj8C\nIQCkSbope5r0KlVdqBeFF8wCfE3plwpelve3jqVIz6MedQ==\n-----END CERTIFICATE-----\n",
7+
"created_at": "2025-03-03T06:42:33.097Z"
8+
}

fixtures/GetClientCertificate.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "49a1d5df-b89a-4998-a469-b1358e282ea5",
3+
"host": "*.acme.com",
4+
"cert": "-----BEGIN CERTIFICATE-----\nMIICDzCCAbagAwIBAgIUMTZlfGA7WcD8e4/zt2MqxvEgQPYwCgYIKoZIzj0EAwIw\nVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhUb29udG93bjES\nMBAGA1UECgwJQWNtZSBJbmMuMREwDwYDVQQDDAhhY21lLmNvbTAeFw0yNTAzMDMw\nNTQ2NTJaFw00OTEwMjMwNTQ2NTJaMHgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\nQTERMA8GA1UEBwwIVG9vbnRvd24xEjAQBgNVBAoMCUFjbWUgSW5jLjEXMBUGA1UE\nAwwOV2lsZSBFLiBDb3lvdGUxHDAaBgkqhkiG9w0BCQEWDXdpbGVAYWNtZS5jb20w\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATAjjDGsKFS1qgdNqziDZoD5hamTfdH\n0P+Ukk1RIue57QYVXhQSyNzcEz15kQnwYezEqfN+FtjtTwdk/CgnAELlo0IwQDAd\nBgNVHQ4EFgQU9C9CpZqM2WMrOs3vAYsc5GbjyzswHwYDVR0jBBgwFoAUnlOyzF/N\nK7YmKQegLdbdyIOCT/UwCgYIKoZIzj0EAwIDRwAwRAIgGgSnBymlH4MkZCVk5DYH\nPdnDo2Xf5uFi1Eyn2LTYP1MCIEtiGtsf0qYv6NzIPd5uTTZoB/8hPrAgM1QzWG4O\n3C/I\n-----END CERTIFICATE-----\n",
5+
"key": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIH0MF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBA5yR3aqy8mZD2wQzp1\nFH2JAgIIADAMBggqhkiG9w0CCQUAMB0GCWCGSAFlAwQBKgQQA49YCnXvfJ2CsQsV\n9C5JJwSBkNkWunSlqyeVW6OFa/+OjlLArgTGvW5ul08qu/145O9PO4Nr2CXeK5N2\nuvHwkWGfD8IVke+sgZPUjLoHsJ4h4AnyxlNHpIxgOfm0CoXT7PTaFb//d5NC6XyB\nK7ZpBzIThGlbuS/b9wp4MPmSaJn5Fci+84VG7KYK5RxU0fcU0rGSBynrZw803wnO\nFjP7qaq5bw==\n-----END ENCRYPTED PRIVATE KEY-----\n",
6+
"ca": "-----BEGIN CERTIFICATE-----\nMIIB/jCCAaOgAwIBAgIUZzxdNpoDYXaNiIBsh0/s++I+ZOEwCgYIKoZIzj0EAwIw\nVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhUb29udG93bjES\nMBAGA1UECgwJQWNtZSBJbmMuMREwDwYDVQQDDAhhY21lLmNvbTAeFw0yNTAzMDMw\nNTQzMDZaFw0yNTA0MDIwNTQzMDZaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\nQTERMA8GA1UEBwwIVG9vbnRvd24xEjAQBgNVBAoMCUFjbWUgSW5jLjERMA8GA1UE\nAwwIYWNtZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARDH3KGK6Vsk1A4\nyGf9ItQIS3yuAOi0n0ihmPzIOOOEN0c758ETABeUdgH55bakdx6q5KYSxf4TuXsJ\n2nCihqVVo1MwUTAdBgNVHQ4EFgQUnlOyzF/NK7YmKQegLdbdyIOCT/UwHwYDVR0j\nBBgwFoAUnlOyzF/NK7YmKQegLdbdyIOCT/UwDwYDVR0TAQH/BAUwAwEB/zAKBggq\nhkjOPQQDAgNJADBGAiEA/cJ9jV8MQz4ypQsFvUatrnbxyHO0f+pJhf09pAk6Kj8C\nIQCkSbope5r0KlVdqBeFF8wCfE3plwpelve3jqVIz6MedQ==\n-----END CERTIFICATE-----\n",
7+
"created_at": "2025-03-03T06:42:33.097Z"
8+
}

types.go

+43
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,25 @@ type Client interface {
368368
groupID int64,
369369
) error
370370

371+
// CreateClientCertificate creates a new client certificate and returns
372+
// the created resource.
373+
CreateClientCertificate(
374+
ctx context.Context,
375+
cs ClientCertificate,
376+
) (*ClientCertificate, error)
377+
378+
// GetClientCertificate retrieves a client certificate.
379+
GetClientCertificate(
380+
ctx context.Context,
381+
ID string,
382+
) (*ClientCertificate, error)
383+
384+
// DeleteClientCertificate deletes a client certificate.
385+
DeleteClientCertificate(
386+
ctx context.Context,
387+
ID string,
388+
) error
389+
371390
// SetAccountId sets ID on a client which is required when using User API keys.
372391
SetAccountId(ID string)
373392

@@ -1069,3 +1088,27 @@ func AlertChannelConfigFromJSON(channelType string, cfgJSON []byte) (interface{}
10691088
}
10701089
return nil, fmt.Errorf("Unknown AlertChannel.config type")
10711090
}
1091+
1092+
type ClientCertificate struct {
1093+
// ID is the Checkly identifier of the client certificate.
1094+
ID string `json:"id,omitempty"`
1095+
1096+
// Host is the host domain that the certificate should be used for.
1097+
Host string `json:"host"`
1098+
1099+
// Certificate is the client certificate in PEM format.
1100+
Certificate string `json:"cert"`
1101+
1102+
// PrivateKey is the private key for the certificate in PEM format.
1103+
PrivateKey string `json:"key"`
1104+
1105+
// Passphrase is an optional passphrase for the private key.
1106+
Passphrase string `json:"passphrase,omitempty"`
1107+
1108+
// TrustedCA is an optional PEM formatted bundle of CA certificates that
1109+
// the client should trust. The bundle may contain many CA certificates.
1110+
TrustedCA string `json:"ca,omitempty"`
1111+
1112+
// CreatedAt is the time when the client certificate was created.
1113+
CreatedAt time.Time `json:"created_at"`
1114+
}

0 commit comments

Comments
 (0)