From 6754da9c210dd040a26f2b9721f7e4e6111cc57f Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Wed, 26 Nov 2025 03:19:55 +0800 Subject: [PATCH 1/8] misc: moved all to /cert-manager and corrected API issues --- backend/bdd/features/environment.py | 5 +- .../features/pki/acme/access-control.feature | 38 +- backend/bdd/features/pki/acme/account.feature | 30 +- backend/bdd/features/pki/acme/auth.feature | 4 +- .../features/pki/acme/cert-profile.feature | 8 +- .../bdd/features/pki/acme/challenge.feature | 12 +- .../bdd/features/pki/acme/directory.feature | 8 +- .../bdd/features/pki/acme/external-ca.feature | 2 +- .../bdd/features/pki/acme/internal-ca.feature | 2 +- backend/bdd/features/pki/acme/nonce.feature | 42 +- backend/bdd/features/pki/acme/order.feature | 28 +- backend/bdd/features/steps/pki_acme.py | 16 +- backend/src/ee/routes/v1/index.ts | 2 +- backend/src/ee/routes/v1/pki-acme-router.ts | 23 +- .../src/ee/services/pki-acme/pki-acme-fns.ts | 2 +- backend/src/lib/api-docs/constants.ts | 4 + .../plugins/add-errors-to-response-schemas.ts | 2 +- .../routes/v1/certificate-authority-router.ts | 10 +- .../certificate-authority-endpoints.ts | 43 +- .../general-certificate-authority-router.ts | 85 ++ .../internal-certificate-authority-router.ts | 412 +++++++++- .../server/routes/v1/certificate-router.ts | 778 ++++++++++++------ .../routes/v1/certificate-template-router.ts | 540 ++++++------ .../v1/deprecated-certificate-router.ts | 680 +++++++++++++++ .../deprecated-certificate-template-router.ts | 395 +++++++++ .../routes/v1/deprecated-pki-alert-router.ts | 205 +++++ backend/src/server/routes/v1/index.ts | 45 +- .../src/server/routes/v1/pki-alert-router.ts | 344 ++++++-- ...ecated-certificate-templates-v2-router.ts} | 0 backend/src/server/routes/v2/index.ts | 2 +- ...r.ts => deprecated-certificates-router.ts} | 0 backend/src/server/routes/v3/index.ts | 2 +- .../acme/acme-certificate-authority-fns.ts | 11 +- .../azure-ad-cs-certificate-authority-fns.ts | 23 +- .../certificate-authority-schemas.ts | 4 - .../certificate-authority-service.ts | 49 +- .../certificate-authority-types.ts | 5 +- .../internal-certificate-authority-fns.ts | 8 +- .../internal-certificate-authority-service.ts | 23 +- .../internal-certificate-authority-types.ts | 4 - .../certificate-v3/certificate-v3-service.ts | 2 +- .../certificate/certificate-service.ts | 39 +- .../services/certificate/certificate-types.ts | 21 +- .../pki-subscriber/pki-subscriber-service.ts | 4 +- .../pki-templates/pki-templates-service.ts | 4 +- frontend/src/const/routes.ts | 4 +- frontend/src/hooks/api/ca/index.tsx | 2 +- frontend/src/hooks/api/ca/mutations.tsx | 33 +- frontend/src/hooks/api/ca/queries.tsx | 51 +- frontend/src/hooks/api/ca/types.ts | 7 +- .../api/certificateProfiles/mutations.tsx | 6 +- .../hooks/api/certificateProfiles/queries.tsx | 10 +- .../api/certificateTemplates/mutations.tsx | 17 +- .../api/certificateTemplates/queries.tsx | 9 +- .../src/hooks/api/certificates/mutations.tsx | 16 +- frontend/src/hooks/api/certificates/types.ts | 4 +- .../src/hooks/api/pkiAlerts/mutations.tsx | 3 + frontend/src/hooks/api/pkiAlerts/queries.tsx | 1 + .../src/hooks/api/pkiAlertsV2/mutations.ts | 6 +- frontend/src/hooks/api/pkiAlertsV2/queries.ts | 10 +- frontend/src/hooks/api/pkiSyncs/mutations.tsx | 44 +- frontend/src/hooks/api/pkiSyncs/queries.tsx | 10 +- .../CertAuthDetailsByIDPage.tsx | 9 +- .../components/CaCrlsSection/CaCrlsTable.tsx | 2 +- .../components/CaDetailsSection.tsx | 12 +- .../CertAuthDetailsByIDPage/route.tsx | 4 +- .../InternalCaInstallForm.tsx | 19 +- .../components/CaModal.tsx | 6 +- .../components/CaSection.tsx | 14 +- .../components/CaTable.tsx | 8 +- .../components/ExternalCaModal.tsx | 5 +- .../components/ExternalCaSection.tsx | 14 +- .../components/ExternalCaTable.tsx | 7 +- .../components/CertificateRevocationModal.tsx | 4 +- .../components/CertificateTemplateModal.tsx | 4 +- .../components/CertificatesSection.tsx | 6 +- .../components/CertificatesTable.tsx | 4 +- .../PkiSubscriberCertificatesTable.tsx | 2 +- .../CertificateProfilesTab/ProfileRow.tsx | 8 +- frontend/src/routeTree.gen.ts | 28 +- frontend/src/routes.ts | 2 +- 81 files changed, 3306 insertions(+), 1051 deletions(-) create mode 100644 backend/src/server/routes/v1/certificate-authority-routers/general-certificate-authority-router.ts create mode 100644 backend/src/server/routes/v1/deprecated-certificate-router.ts create mode 100644 backend/src/server/routes/v1/deprecated-certificate-template-router.ts create mode 100644 backend/src/server/routes/v1/deprecated-pki-alert-router.ts rename backend/src/server/routes/v2/{certificate-templates-v2-router.ts => deprecated-certificate-templates-v2-router.ts} (100%) rename backend/src/server/routes/v3/{certificates-router.ts => deprecated-certificates-router.ts} (100%) diff --git a/backend/bdd/features/environment.py b/backend/bdd/features/environment.py index 976998c72..52fda3eca 100644 --- a/backend/bdd/features/environment.py +++ b/backend/bdd/features/environment.py @@ -87,14 +87,13 @@ def bootstrap_infisical(context: Context): ca_slug = faker.slug() resp = client.post( - "/api/v1/pki/ca/internal", + "/api/v1/cert-manager/ca/internal", headers=headers, json={ "projectId": project["id"], "name": ca_slug, "type": "internal", "status": "active", - "enableDirectIssuance": True, "configuration": { "type": "root", "organization": "Infisican Inc", @@ -115,7 +114,7 @@ def bootstrap_infisical(context: Context): cert_template_slug = faker.slug() resp = client.post( - "/api/v2/certificate-templates", + "/api/v1/cert-manager/certificate-templates", headers=headers, json={ "projectId": project["id"], diff --git a/backend/bdd/features/pki/acme/access-control.feature b/backend/bdd/features/pki/acme/access-control.feature index 50588be76..053127077 100644 --- a/backend/bdd/features/pki/acme/access-control.feature +++ b/backend/bdd/features/pki/acme/access-control.feature @@ -2,7 +2,7 @@ Feature: Access Control Scenario Outline: Access resources across different account Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account0 Then I memorize acme_account0.uri with jq "capture("/(?[^/]+)$") | .id" as account0_id When I create certificate signing request as csr @@ -34,7 +34,7 @@ Feature: Access Control Then the value response.status_code should not be equal to 404 And I put away current ACME client as client0 - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email maidu@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account1 Then I peak and memorize the next nonce as nonce When I send a raw ACME request to "" @@ -53,7 +53,7 @@ Feature: Access Control Examples: Endpoints | src_var | jq | dest_var | url | payload | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account0_id}/orders | | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account0_id}/orders | | | order | . | not_used | {order.uri} | | | order | . | not_used | {order.uri}/finalize | {\"csr\": \"\"} | | order | . | not_used | {order.uri}/certificate | | @@ -62,7 +62,7 @@ Feature: Access Control Scenario Outline: Access resources across a different profiles Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account0 Then I memorize acme_account0.uri with jq "capture("/(?[^/]+)$") | .id" as account0_id When I create certificate signing request as csr @@ -96,7 +96,7 @@ Feature: Access Control Given I make a random slug as profile_slug Given I use AUTH_TOKEN for authentication - When I send a "POST" request to "/api/v1/pki/certificate-profiles" with JSON payload + When I send a "POST" request to "/api/v1/cert-manager/certificate-profiles" with JSON payload """ { "projectId": "{PROJECT_ID}", @@ -110,10 +110,10 @@ Feature: Access Control """ Then the value response.status_code should be equal to 200 Then I memorize response with jq ".certificateProfile.id" as profile_id - When I send a "GET" request to "/api/v1/pki/certificate-profiles/{profile_id}/acme/eab-secret/reveal" + When I send a "GET" request to "/api/v1/cert-manager/certificate-profiles/{profile_id}/acme/eab-secret/reveal" Then I memorize response with jq ".eabKid" as eab_kid And I memorize response with jq ".eabSecret" as eab_secret - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{profile_id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{profile_id}/directory" Then I register a new ACME account with email maidu@infisical.com and EAB key id "{eab_kid}" with secret "{eab_secret}" as acme_account1 Then I peak and memorize the next nonce as nonce Then I memorize with jq "" as @@ -133,7 +133,7 @@ Feature: Access Control Examples: Endpoints | src_var | jq | dest_var | url | payload | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account0_id}/orders | | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account0_id}/orders | | | order | . | not_used | {order.uri} | | | order | . | not_used | {order.uri}/finalize | {\"csr\": \"\"} | | order | . | not_used | {order.uri}/certificate | | @@ -143,7 +143,7 @@ Feature: Access Control Scenario Outline: Access resources across a different profile with the same key pair Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account0 Then I memorize acme_account0.uri with jq "capture("/(?[^/]+)$") | .id" as account0_id When I create certificate signing request as csr @@ -177,7 +177,7 @@ Feature: Access Control Given I make a random slug as profile_slug Given I use AUTH_TOKEN for authentication - When I send a "POST" request to "/api/v1/pki/certificate-profiles" with JSON payload + When I send a "POST" request to "/api/v1/cert-manager/certificate-profiles" with JSON payload """ { "projectId": "{PROJECT_ID}", @@ -191,10 +191,10 @@ Feature: Access Control """ Then the value response.status_code should be equal to 200 Then I memorize response with jq ".certificateProfile.id" as profile_id - When I send a "GET" request to "/api/v1/pki/certificate-profiles/{profile_id}/acme/eab-secret/reveal" + When I send a "GET" request to "/api/v1/cert-manager/certificate-profiles/{profile_id}/acme/eab-secret/reveal" Then I memorize response with jq ".eabKid" as eab_kid And I memorize response with jq ".eabSecret" as eab_secret - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{profile_id}/directory" with the key pair from client0 + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{profile_id}/directory" with the key pair from client0 Then I register a new ACME account with email maidu@infisical.com and EAB key id "{eab_kid}" with secret "{eab_secret}" as acme_account1 Then I peak and memorize the next nonce as nonce Then I memorize with jq "" as @@ -214,7 +214,7 @@ Feature: Access Control Examples: Endpoints | src_var | jq | dest_var | url | payload | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account0_id}/orders | | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account0_id}/orders | | | order | . | not_used | {order.uri} | | | order | . | not_used | {order.uri}/finalize | {\"csr\": \"\"} | | order | . | not_used | {order.uri}/certificate | | @@ -223,7 +223,7 @@ Feature: Access Control Scenario Outline: URL mismatch Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account Then I memorize acme_account.uri with jq "capture("/(?[^/]+)$") | .id" as account_id When I create certificate signing request as csr @@ -258,8 +258,8 @@ Feature: Access Control Examples: Endpoints | src_var | jq | dest_var | actual_url | bad_url | error_detail | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | BAD | Invalid URL in the protected header | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | https://evil.com/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | URL mismatch in the protected header | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | BAD | Invalid URL in the protected header | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | https://evil.com/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | URL mismatch in the protected header | | order | . | not_used | {order.uri} | BAD | Invalid URL in the protected header | | order | . | not_used | {order.uri} | https://example.com/acmes/orders/FOOBAR | URL mismatch in the protected header | | order | . | not_used | {order.uri}/finalize | BAD | Invalid URL in the protected header | @@ -273,7 +273,7 @@ Feature: Access Control Scenario Outline: Send KID and JWK in the same time Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And I memorize acme_account.uri with jq "capture("/(?[^/]+)$") | .id" as account_id When I create certificate signing request as csr @@ -312,8 +312,8 @@ Feature: Access Control Examples: Endpoints | src_var | jq | dest_var | url | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order | | order | . | not_used | {order.uri} | | order | . | not_used | {order.uri}/finalize | | order | . | not_used | {order.uri}/certificate | diff --git a/backend/bdd/features/pki/acme/account.feature b/backend/bdd/features/pki/acme/account.feature index 14e304c6c..c7eb25a53 100644 --- a/backend/bdd/features/pki/acme/account.feature +++ b/backend/bdd/features/pki/acme/account.feature @@ -2,13 +2,13 @@ Feature: Account Scenario: Create a new account Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account - And the value acme_account.uri with jq "." should match pattern {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/(.+) + And the value acme_account.uri with jq "." should match pattern {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/(.+) Scenario: Create a new account with the same key pair twice Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And I memorize acme_account.uri as kid And I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account2 @@ -17,7 +17,7 @@ Feature: Account Scenario: Find an existing account Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And I memorize acme_account.uri as account_uri And I find the existing ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as retrieved_account @@ -26,7 +26,7 @@ Feature: Account # Note: This is a very special case for cert-manager. Scenario: Create a new account with EAB then retrieve it without EAB Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And I memorize acme_account.uri as account_uri And I find the existing ACME account without EAB as retrieved_account @@ -35,13 +35,13 @@ Feature: Account Scenario: Create a new account without EAB Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com without EAB And the value error with jq ".type" should be equal to "urn:ietf:params:acme:error:externalAccountRequired" Scenario Outline: Scenario: Create a new account with bad EAB credentials Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "" with secret "" as acme_account And the value error with jq ".type" should be equal to "" And the value error with jq ".detail" should be equal to "" @@ -57,17 +57,17 @@ Feature: Account Scenario Outline: Scenario: Create a new account with bad EAB url Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" And I use a different new-account URL "" for EAB signature Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And the value error with jq ".type" should be equal to "urn:ietf:params:acme:error:externalAccountRequired" And the value error with jq ".detail" should be equal to "External account binding URL mismatch" Examples: Bad URLs - | url | - | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-account-bad | - | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-account?foo=bar | - | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-account#foobar | - | {BASE_URL}/acme/new-account | - | https://example.com/api/v1/pki/acme/profiles/{acme_profile.id}/new-account-bad | - | bad | + | url | + | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-account-bad | + | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-account?foo=bar | + | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-account#foobar | + | {BASE_URL}/acme/new-account | + | https://example.com/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-account-bad | + | bad | diff --git a/backend/bdd/features/pki/acme/auth.feature b/backend/bdd/features/pki/acme/auth.feature index 46cc9d4e2..757a182c8 100644 --- a/backend/bdd/features/pki/acme/auth.feature +++ b/backend/bdd/features/pki/acme/auth.feature @@ -2,7 +2,7 @@ Feature: Authorization Scenario: Get authorization Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr @@ -14,7 +14,7 @@ Feature: Authorization Then I create a RSA private key pair as cert_key And I sign the certificate signing request csr with private key cert_key and output it as csr_pem in PEM format And I submit the certificate signing request PEM csr_pem certificate order to the ACME server as order - And the value order.authorizations[0].uri with jq "." should match pattern {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/authorizations/(.+) + And the value order.authorizations[0].uri with jq "." should match pattern {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/authorizations/(.+) And the value order.authorizations[0].body with jq ".status" should be equal to "pending" And the value order.authorizations[0].body with jq ".challenges | map(pick(.type, .status)) | sort_by(.type)" should be equal to json """ diff --git a/backend/bdd/features/pki/acme/cert-profile.feature b/backend/bdd/features/pki/acme/cert-profile.feature index 3c292e8ba..4c3b84ab9 100644 --- a/backend/bdd/features/pki/acme/cert-profile.feature +++ b/backend/bdd/features/pki/acme/cert-profile.feature @@ -3,7 +3,7 @@ Feature: ACME Cert Profile Scenario: Create a cert profile Given I make a random slug as profile_slug And I use AUTH_TOKEN for authentication - When I send a "POST" request to "/api/v1/pki/certificate-profiles" with JSON payload + When I send a "POST" request to "/api/v1/cert-manager/certificate-profiles" with JSON payload """ { "projectId": "{PROJECT_ID}", @@ -25,7 +25,7 @@ Feature: ACME Cert Profile Scenario: Reveal EAB secret Given I make a random slug as profile_slug And I use AUTH_TOKEN for authentication - When I send a "POST" request to "/api/v1/pki/certificate-profiles" with JSON payload + When I send a "POST" request to "/api/v1/cert-manager/certificate-profiles" with JSON payload """ { "projectId": "{PROJECT_ID}", @@ -39,11 +39,11 @@ Feature: ACME Cert Profile """ Then the value response.status_code should be equal to 200 And I memorize response with jq ".certificateProfile.id" as profile_id - When I send a "GET" request to "/api/v1/pki/certificate-profiles/{profile_id}/acme/eab-secret/reveal" + When I send a "GET" request to "/api/v1/cert-manager/certificate-profiles/{profile_id}/acme/eab-secret/reveal" Then the value response.status_code should be equal to 200 And the value response with jq ".eabKid" should be equal to "{profile_id}" And the value response with jq ".eabSecret" should be present And I memorize response with jq ".eabKid" as eab_kid And I memorize response with jq ".eabSecret" as eab_secret - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{profile_id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{profile_id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{eab_kid}" with secret "{eab_secret}" as acme_account diff --git a/backend/bdd/features/pki/acme/challenge.feature b/backend/bdd/features/pki/acme/challenge.feature index 67f73aab2..21c63329f 100644 --- a/backend/bdd/features/pki/acme/challenge.feature +++ b/backend/bdd/features/pki/acme/challenge.feature @@ -2,7 +2,7 @@ Feature: Challenge Scenario: Validate challenge Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr @@ -24,7 +24,7 @@ Feature: Challenge Scenario: Validate challenges for multiple domains Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr @@ -58,7 +58,7 @@ Feature: Challenge Scenario: Did not finish all challenges Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr @@ -153,7 +153,7 @@ Feature: Challenge Scenario: CSR names mismatch with order identifier Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr @@ -165,13 +165,13 @@ Feature: Challenge And I create a RSA private key pair as cert_key And I sign the certificate signing request csr with private key cert_key and output it as csr_pem in PEM format Then I peak and memorize the next nonce as nonce - When I send a raw ACME request to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order" + When I send a raw ACME request to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order" """ { "protected": { "alg": "RS256", "nonce": "{nonce}", - "url": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order", + "url": "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order", "kid": "{acme_account.uri}" }, "payload": { diff --git a/backend/bdd/features/pki/acme/directory.feature b/backend/bdd/features/pki/acme/directory.feature index 53084a681..30a94af38 100644 --- a/backend/bdd/features/pki/acme/directory.feature +++ b/backend/bdd/features/pki/acme/directory.feature @@ -2,14 +2,14 @@ Feature: Directory Scenario: Get the directory of ACME service urls Given I have an ACME cert profile as "acme_profile" - When I send a "GET" request to "/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I send a "GET" request to "/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then the response status code should be "200" And the response body should match JSON value """ { - "newNonce": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-nonce", - "newAccount": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-account", - "newOrder": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order", + "newNonce": "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-nonce", + "newAccount": "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-account", + "newOrder": "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order", "meta": { "externalAccountRequired": true } diff --git a/backend/bdd/features/pki/acme/external-ca.feature b/backend/bdd/features/pki/acme/external-ca.feature index 26bfd84ad..fd0c3f399 100644 --- a/backend/bdd/features/pki/acme/external-ca.feature +++ b/backend/bdd/features/pki/acme/external-ca.feature @@ -87,7 +87,7 @@ Feature: External CA """ Then I memorize cert_template with jq ".certificateTemplate.id" as cert_template_id Given I create an ACME profile with ca {ext_ca_id} and template {cert_template_id} as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr diff --git a/backend/bdd/features/pki/acme/internal-ca.feature b/backend/bdd/features/pki/acme/internal-ca.feature index 9db4328d2..934b7bef3 100644 --- a/backend/bdd/features/pki/acme/internal-ca.feature +++ b/backend/bdd/features/pki/acme/internal-ca.feature @@ -2,7 +2,7 @@ Feature: Internal CA Scenario: CSR with SANs only Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr diff --git a/backend/bdd/features/pki/acme/nonce.feature b/backend/bdd/features/pki/acme/nonce.feature index 9a55ae284..93fc3f981 100644 --- a/backend/bdd/features/pki/acme/nonce.feature +++ b/backend/bdd/features/pki/acme/nonce.feature @@ -2,13 +2,13 @@ Feature: Nonce Scenario: Generate a new nonce Given I have an ACME cert profile as "acme_profile" - When I send a "HEAD" request to "/api/v1/pki/acme/profiles/{acme_profile.id}/new-nonce" + When I send a "HEAD" request to "/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-nonce" Then the response status code should be "200" And the response header "Replay-Nonce" should contains non-empty value Scenario Outline: Send a bad nonce to account endpoints Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And I memorize acme_account.uri with jq "capture("/(?[^/]+)$") | .id" as account_id When I create certificate signing request as csr @@ -40,18 +40,18 @@ Feature: Nonce And the value response with jq ".detail" should be equal to "Invalid nonce" Examples: Endpoints - | src_var | jq | dest_var | url | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order | - | order | . | not_used | {order.uri} | - | order | . | not_used | {order.uri}/finalize | - | order | . | not_used | {order.uri}/certificate | - | order | .authorizations[0].uri | auth_uri | {auth_uri} | - | order | .authorizations[0].body.challenges[0].url | challenge_uri | {challenge_uri} | + | src_var | jq | dest_var | url | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order | + | order | . | not_used | {order.uri} | + | order | . | not_used | {order.uri}/finalize | + | order | . | not_used | {order.uri}/certificate | + | order | .authorizations[0].uri | auth_uri | {auth_uri} | + | order | .authorizations[0].body.challenges[0].url | challenge_uri | {challenge_uri} | Scenario Outline: Send the same nonce twice Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And I memorize acme_account.uri with jq "capture("/(?[^/]+)$") | .id" as account_id When I create certificate signing request as csr @@ -65,13 +65,13 @@ Feature: Nonce And I sign the certificate signing request csr with private key cert_key and output it as csr_pem in PEM format And I submit the certificate signing request PEM csr_pem certificate order to the ACME server as order And I peak and memorize the next nonce as nonce_value - When I send a raw ACME request to "/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders" + When I send a raw ACME request to "/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders" """ { "protected": { "alg": "RS256", "nonce": "{nonce_value}", - "url": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders", + "url": "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders", "kid": "{acme_account.uri}" }, "payload": {} @@ -97,11 +97,11 @@ Feature: Nonce And the value response with jq ".detail" should be equal to "Invalid nonce" Examples: Endpoints - | src_var | jq | dest_var | url | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | - | order | . | not_used | {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order | - | order | . | not_used | {order.uri} | - | order | . | not_used | {order.uri}/finalize | - | order | . | not_used | {order.uri}/certificate | - | order | .authorizations[0].uri | auth_uri | {auth_uri} | - | order | .authorizations[0].body.challenges[0].url | challenge_uri | {challenge_uri} | + | src_var | jq | dest_var | url | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/accounts/{account_id}/orders | + | order | . | not_used | {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order | + | order | . | not_used | {order.uri} | + | order | . | not_used | {order.uri}/finalize | + | order | . | not_used | {order.uri}/certificate | + | order | .authorizations[0].uri | auth_uri | {auth_uri} | + | order | .authorizations[0].body.challenges[0].url | challenge_uri | {challenge_uri} | diff --git a/backend/bdd/features/pki/acme/order.feature b/backend/bdd/features/pki/acme/order.feature index 19f467f00..199cd4aa6 100644 --- a/backend/bdd/features/pki/acme/order.feature +++ b/backend/bdd/features/pki/acme/order.feature @@ -2,7 +2,7 @@ Feature: Order Scenario: Create a new order Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr @@ -14,15 +14,15 @@ Feature: Order Then I create a RSA private key pair as cert_key And I sign the certificate signing request csr with private key cert_key and output it as csr_pem in PEM format And I submit the certificate signing request PEM csr_pem certificate order to the ACME server as order - And the value order.uri with jq "." should match pattern {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/orders/(.+) + And the value order.uri with jq "." should match pattern {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/orders/(.+) And the value order.body with jq ".status" should be equal to "pending" And the value order.body with jq ".identifiers" should be equal to [{"type": "dns", "value": "localhost"}] - And the value order.body with jq ".finalize" should match pattern {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/orders/(.+)/finalize - And the value order.body with jq "all(.authorizations[]; startswith("{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/authorizations/"))" should be equal to true + And the value order.body with jq ".finalize" should match pattern {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/orders/(.+)/finalize + And the value order.body with jq "all(.authorizations[]; startswith("{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/authorizations/"))" should be equal to true Scenario: Create a new order with SANs Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr @@ -52,7 +52,7 @@ Feature: Order Scenario: Fetch an order Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr @@ -67,21 +67,21 @@ Feature: Order And I send an ACME post-as-get to order.uri as fetched_order And the value fetched_order with jq ".status" should be equal to "pending" And the value fetched_order with jq ".identifiers" should be equal to [{"type": "dns", "value": "localhost"}] - And the value fetched_order with jq ".finalize" should match pattern {BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/orders/(.+)/finalize - And the value fetched_order with jq "all(.authorizations[]; startswith("{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/authorizations/"))" should be equal to true + And the value fetched_order with jq ".finalize" should match pattern {BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/orders/(.+)/finalize + And the value fetched_order with jq "all(.authorizations[]; startswith("{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/authorizations/"))" should be equal to true Scenario Outline: Create an order with invalid identifier types Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And I peak and memorize the next nonce as nonce - When I send a raw ACME request to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order" + When I send a raw ACME request to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order" """ { "protected": { "alg": "RS256", "nonce": "{nonce}", - "url": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order", + "url": "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order", "kid": "{acme_account.uri}" }, "payload": { @@ -105,16 +105,16 @@ Feature: Order Scenario Outline: Create an order with invalid identifier values Given I have an ACME cert profile as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account And I peak and memorize the next nonce as nonce - When I send a raw ACME request to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order" + When I send a raw ACME request to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order" """ { "protected": { "alg": "RS256", "nonce": "{nonce}", - "url": "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/new-order", + "url": "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/new-order", "kid": "{acme_account.uri}" }, "payload": { diff --git a/backend/bdd/features/steps/pki_acme.py b/backend/bdd/features/steps/pki_acme.py index 353ec942d..401ea89e3 100644 --- a/backend/bdd/features/steps/pki_acme.py +++ b/backend/bdd/features/steps/pki_acme.py @@ -56,7 +56,7 @@ def step_impl(context: Context, profile_var: str): profile_slug = faker.slug() jwt_token = context.vars["AUTH_TOKEN"] response = context.http_client.post( - "/api/v1/pki/certificate-profiles", + "/api/v1/cert-manager/certificate-profiles", headers=dict(authorization="Bearer {}".format(jwt_token)), json={ "projectId": context.vars["PROJECT_ID"], @@ -74,7 +74,7 @@ def step_impl(context: Context, profile_var: str): kid = profile_id response = context.http_client.get( - f"/api/v1/pki/certificate-profiles/{profile_id}/acme/eab-secret/reveal", + f"/api/v1/cert-manager/certificate-profiles/{profile_id}/acme/eab-secret/reveal", headers=dict(authorization="Bearer {}".format(jwt_token)), ) response.raise_for_status() @@ -153,7 +153,7 @@ def step_impl(context: Context, var_name: str): ca_slug = faker.slug() config = replace_vars(json.loads(context.text), context.vars) response = context.http_client.post( - "/api/v1/pki/ca/acme", + "/api/v1/cert-manager/ca/acme", headers=dict(authorization="Bearer {}".format(jwt_token)), json={ "projectId": context.vars["PROJECT_ID"], @@ -174,7 +174,7 @@ def step_impl(context: Context, var_name: str): template_slug = faker.slug() config = replace_vars(json.loads(context.text), context.vars) response = context.http_client.post( - "/api/v2/certificate-templates", + "/api/v1/cert-manager/certificate-templates", headers=dict(authorization="Bearer {}".format(jwt_token)), json={ "projectId": context.vars["PROJECT_ID"], @@ -194,7 +194,7 @@ def step_impl(context: Context, ca_id: str, template_id: str, profile_var: str): profile_slug = faker.slug() jwt_token = context.vars["AUTH_TOKEN"] response = context.http_client.post( - "/api/v1/pki/certificate-profiles", + "/api/v1/cert-manager/certificate-profiles", headers=dict(authorization="Bearer {}".format(jwt_token)), json={ "projectId": context.vars["PROJECT_ID"], @@ -212,7 +212,7 @@ def step_impl(context: Context, ca_id: str, template_id: str, profile_var: str): kid = profile_id response = context.http_client.get( - f"/api/v1/pki/certificate-profiles/{profile_id}/acme/eab-secret/reveal", + f"/api/v1/cert-manager/certificate-profiles/{profile_id}/acme/eab-secret/reveal", headers=dict(authorization="Bearer {}".format(jwt_token)), ) response.raise_for_status() @@ -236,7 +236,7 @@ def step_impl(context: Context, profile_var: str): profile_slug = faker.slug() jwt_token = context.vars["AUTH_TOKEN"] response = context.http_client.post( - "/api/v1/pki/certificate-profiles", + "/api/v1/cert-manager/certificate-profiles", headers=dict(authorization="Bearer {}".format(jwt_token)), json={ "projectId": context.vars["PROJECT_ID"], @@ -254,7 +254,7 @@ def step_impl(context: Context, profile_var: str): kid = profile_id response = context.http_client.get( - f"/api/v1/pki/certificate-profiles/{profile_id}/acme/eab-secret/reveal", + f"/api/v1/cert-manager/certificate-profiles/{profile_id}/acme/eab-secret/reveal", headers=dict(authorization="Bearer {}".format(jwt_token)), ) response.raise_for_status() diff --git a/backend/src/ee/routes/v1/index.ts b/backend/src/ee/routes/v1/index.ts index 7ff9ec09a..367c2833c 100644 --- a/backend/src/ee/routes/v1/index.ts +++ b/backend/src/ee/routes/v1/index.ts @@ -110,7 +110,7 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => { await pkiRouter.register(registerCaCrlRouter, { prefix: "/crl" }); await pkiRouter.register(registerPkiAcmeRouter, { prefix: "/acme" }); }, - { prefix: "/pki" } + { prefix: "/cert-manager" } ); await server.register( diff --git a/backend/src/ee/routes/v1/pki-acme-router.ts b/backend/src/ee/routes/v1/pki-acme-router.ts index c4ccf6be5..a73f955ae 100644 --- a/backend/src/ee/routes/v1/pki-acme-router.ts +++ b/backend/src/ee/routes/v1/pki-acme-router.ts @@ -77,7 +77,8 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { done(error, undefined); } }); - // GET /api/v1/pki/acme/profiles//directory + + // GET /api/v1/cert-manager/acme/profiles//directory // Directory (RFC 8555 Section 7.1.1) server.route({ method: "GET", @@ -99,7 +100,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { handler: async (req) => server.services.pkiAcme.getAcmeDirectory(req.params.profileId) }); - // HEAD /api/v1/pki/acme/profiles//new-nonce + // HEAD /api/v1/cert-manager/acme/profiles//new-nonce // New Nonce (RFC 8555 Section 7.2) server.route({ method: "HEAD", @@ -126,7 +127,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { } }); - // POST /api/v1/pki/acme/profiles//new-account + // POST /api/v1/cert-manager/acme/profiles//new-account // New Account (RFC 8555 Section 7.3) server.route({ method: "POST", @@ -163,7 +164,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { } }); - // POST /api/v1/pki/acme/profiles//accounts/ + // POST /api/v1/cert-manager/acme/profiles//accounts/ // Account Deactivation (RFC 8555 Section 7.3.6) server.route({ method: "POST", @@ -200,7 +201,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { } }); - // POST /api/v1/pki/acme/profiles//new-order + // POST /api/v1/cert-manager/acme/profiles//new-order // New Certificate Order (RFC 8555 Section 7.4) server.route({ method: "POST", @@ -235,7 +236,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { } }); - // POST /api/v1/pki/acme/profiles//orders/ + // POST /api/v1/cert-manager/acme/profiles//orders/ // Get Order (RFC 8555 Section 7.1.3) server.route({ method: "POST", @@ -271,7 +272,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { } }); - // POST /api/v1/pki/acme/profiles//orders//finalize + // POST /api/v1/cert-manager/acme/profiles//orders//finalize // Applying for Certificate Issuance (RFC 8555 Section 7.4) server.route({ method: "POST", @@ -308,7 +309,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { ); } }); - // POST /api/v1/pki/acme/profiles//accounts//orders + // POST /api/v1/cert-manager/acme/profiles//accounts//orders // List Orders (RFC 8555 Section 7.1.2.1) server.route({ method: "POST", @@ -344,7 +345,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { } }); - // POST /api/v1/pki/acme/profiles//orders//certificate + // POST /api/v1/cert-manager/acme/profiles//orders//certificate // Download Certificate (RFC 8555 Section 7.4.2) server.route({ method: "POST", @@ -377,7 +378,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { } }); - // POST /api/v1/pki/acme/profiles//authorizations/ + // POST /api/v1/cert-manager/acme/profiles//authorizations/ // Identifier Authorization (RFC 8555 Section 7.5) server.route({ method: "POST", @@ -411,7 +412,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => { } }); - // POST /api/v1/pki/acme/profiles//authorizations//challenges/ + // POST /api/v1/cert-manager/acme/profiles//authorizations//challenges/ // Respond to Challenge (RFC 8555 Section 7.5.1) server.route({ method: "POST", diff --git a/backend/src/ee/services/pki-acme/pki-acme-fns.ts b/backend/src/ee/services/pki-acme/pki-acme-fns.ts index a5206d036..759e3cdf9 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-fns.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-fns.ts @@ -8,7 +8,7 @@ import { AcmeAccountDoesNotExistError } from "./pki-acme-errors"; export const buildUrl = (profileId: string, path: string): string => { const appCfg = getConfig(); const baseUrl = appCfg.SITE_URL ?? ""; - return `${baseUrl}/api/v1/pki/acme/profiles/${profileId}${path}`; + return `${baseUrl}/api/v1/cert-manager/acme/profiles/${profileId}${path}`; }; export const extractAccountIdFromKid = (kid: string, profileId: string): string => { diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 970f9a1a0..3c8972248 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -1962,9 +1962,11 @@ export const CERTIFICATE_AUTHORITIES = { export const CERTIFICATES = { GET: { + id: "The ID of the certificate to get.", serialNumber: "The serial number of the certificate to get." }, REVOKE: { + id: "The ID of the certificate to revoke.", serialNumber: "The serial number of the certificate to revoke. The revoked certificate will be added to the certificate revocation list (CRL) of the CA.", revocationReason: "The reason for revoking the certificate.", @@ -1972,9 +1974,11 @@ export const CERTIFICATES = { serialNumberRes: "The serial number of the revoked certificate." }, DELETE: { + id: "The ID of the certificate to delete.", serialNumber: "The serial number of the certificate to delete." }, GET_CERT: { + id: "The ID of the certificate to get the certificate body and certificate chain for.", serialNumber: "The serial number of the certificate to get the certificate body and certificate chain for.", certificate: "The certificate body of the certificate.", certificateChain: "The certificate chain of the certificate.", diff --git a/backend/src/server/plugins/add-errors-to-response-schemas.ts b/backend/src/server/plugins/add-errors-to-response-schemas.ts index 6337bae0f..a09f34a0e 100644 --- a/backend/src/server/plugins/add-errors-to-response-schemas.ts +++ b/backend/src/server/plugins/add-errors-to-response-schemas.ts @@ -6,7 +6,7 @@ import { DefaultResponseErrorsSchema } from "../routes/sanitizedSchemas"; const isScimRoutes = (pathname: string) => pathname.startsWith("/api/v1/scim/Users") || pathname.startsWith("/api/v1/scim/Groups"); -const isAcmeRoutes = (pathname: string) => pathname.startsWith("/api/v1/pki/acme/"); +const isAcmeRoutes = (pathname: string) => pathname.startsWith("/api/v1/cert-manager/acme/"); export const addErrorsToResponseSchemas = fp(async (server) => { server.addHook("onRoute", (routeOptions) => { diff --git a/backend/src/server/routes/v1/certificate-authority-router.ts b/backend/src/server/routes/v1/certificate-authority-router.ts index 3d15b473a..2917270ef 100644 --- a/backend/src/server/routes/v1/certificate-authority-router.ts +++ b/backend/src/server/routes/v1/certificate-authority-router.ts @@ -85,7 +85,6 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { actorAuthMethod: req.permission.authMethod, isInternal: false, actorOrgId: req.permission.orgId, - enableDirectIssuance: !req.body.requireTemplateForIssuance, ...req.body }); @@ -220,7 +219,6 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { isInternal: false, actorAuthMethod: req.permission.authMethod, actorOrgId: req.permission.orgId, - enableDirectIssuance: !req.body.requireTemplateForIssuance, ...req.body }); @@ -617,6 +615,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { } }); + // TODO: DEPRECATE server.route({ method: "POST", url: "/:caId/issue-certificate", @@ -625,7 +624,6 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { - hide: false, tags: [ApiDocsTags.PkiCertificateAuthorities], description: "Issue certificate from CA", params: z.object({ @@ -711,6 +709,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { } }); + // TODO: DEPRECATE server.route({ method: "POST", url: "/:caId/sign-certificate", @@ -719,7 +718,6 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { - hide: false, tags: [ApiDocsTags.PkiCertificateAuthorities], description: "Sign certificate from CA", params: z.object({ @@ -805,6 +803,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { } }); + // TODO: DEPRECATE server.route({ method: "GET", url: "/:caId/certificate-templates", @@ -813,7 +812,6 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { - hide: false, tags: [ApiDocsTags.PkiCertificateAuthorities], description: "Get list of certificate templates for the CA", params: z.object({ @@ -854,6 +852,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { } }); + // TODO: DEPRECATE server.route({ method: "GET", url: "/:caId/crls", @@ -862,7 +861,6 @@ export const registerCaRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { - hide: false, tags: [ApiDocsTags.PkiCertificateAuthorities], description: "Get list of CRLs of the CA", params: z.object({ diff --git a/backend/src/server/routes/v1/certificate-authority-routers/certificate-authority-endpoints.ts b/backend/src/server/routes/v1/certificate-authority-routers/certificate-authority-endpoints.ts index 01952c7f4..7e89a99a1 100644 --- a/backend/src/server/routes/v1/certificate-authority-routers/certificate-authority-endpoints.ts +++ b/backend/src/server/routes/v1/certificate-authority-routers/certificate-authority-endpoints.ts @@ -28,14 +28,10 @@ export const registerCertificateAuthorityEndpoints = < projectId: string; status: CaStatus; configuration: I["configuration"]; - enableDirectIssuance: boolean; }>; updateSchema: z.ZodType<{ - projectId: string; - name?: string; status?: CaStatus; configuration?: I["configuration"]; - enableDirectIssuance?: boolean; }>; responseSchema: z.ZodTypeAny; }) => { @@ -83,7 +79,7 @@ export const registerCertificateAuthorityEndpoints = < server.route({ method: "GET", - url: "/:caName", + url: "/:id", config: { rateLimit: readLimit }, @@ -91,10 +87,7 @@ export const registerCertificateAuthorityEndpoints = < hide: false, tags: [ApiDocsTags.PkiCertificateAuthorities], params: z.object({ - caName: z.string() - }), - querystring: z.object({ - projectId: z.string().uuid() + id: z.string() }), response: { 200: responseSchema @@ -102,14 +95,12 @@ export const registerCertificateAuthorityEndpoints = < }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const { caName } = req.params; - const { projectId } = req.query; + const { id } = req.params; - const certificateAuthority = - (await server.services.certificateAuthority.findCertificateAuthorityByNameAndProjectId( - { caName, type: caType, projectId }, - req.permission - )) as T; + const certificateAuthority = (await server.services.certificateAuthority.findCertificateAuthorityById( + { id, type: caType }, + req.permission + )) as T; await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, @@ -166,7 +157,7 @@ export const registerCertificateAuthorityEndpoints = < server.route({ method: "PATCH", - url: "/:caName", + url: "/:id", config: { rateLimit: writeLimit }, @@ -174,7 +165,7 @@ export const registerCertificateAuthorityEndpoints = < hide: false, tags: [ApiDocsTags.PkiCertificateAuthorities], params: z.object({ - caName: z.string() + id: z.string() }), body: updateSchema, response: { @@ -183,13 +174,13 @@ export const registerCertificateAuthorityEndpoints = < }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const { caName } = req.params; + const { id } = req.params; const certificateAuthority = (await server.services.certificateAuthority.updateCertificateAuthority( { ...req.body, type: caType, - caName + id }, req.permission )) as T; @@ -213,7 +204,7 @@ export const registerCertificateAuthorityEndpoints = < server.route({ method: "DELETE", - url: "/:caName", + url: "/:id", config: { rateLimit: writeLimit }, @@ -221,10 +212,7 @@ export const registerCertificateAuthorityEndpoints = < hide: false, tags: [ApiDocsTags.PkiCertificateAuthorities], params: z.object({ - caName: z.string() - }), - body: z.object({ - projectId: z.string().uuid() + id: z.string() }), response: { 200: responseSchema @@ -232,11 +220,10 @@ export const registerCertificateAuthorityEndpoints = < }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const { caName } = req.params; - const { projectId } = req.body; + const { id } = req.params; const certificateAuthority = (await server.services.certificateAuthority.deleteCertificateAuthority( - { caName, type: caType, projectId }, + { id, type: caType }, req.permission )) as T; diff --git a/backend/src/server/routes/v1/certificate-authority-routers/general-certificate-authority-router.ts b/backend/src/server/routes/v1/certificate-authority-routers/general-certificate-authority-router.ts new file mode 100644 index 000000000..7a7281d57 --- /dev/null +++ b/backend/src/server/routes/v1/certificate-authority-routers/general-certificate-authority-router.ts @@ -0,0 +1,85 @@ +import { z } from "zod"; + +import { EventType } from "@app/ee/services/audit-log/audit-log-types"; +import { ApiDocsTags } from "@app/lib/api-docs"; +import { readLimit } from "@app/server/config/rateLimiter"; +import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { AuthMode } from "@app/services/auth/auth-type"; +import { AcmeCertificateAuthoritySchema } from "@app/services/certificate-authority/acme/acme-certificate-authority-schemas"; +import { AzureAdCsCertificateAuthoritySchema } from "@app/services/certificate-authority/azure-ad-cs/azure-ad-cs-certificate-authority-schemas"; +import { CaType } from "@app/services/certificate-authority/certificate-authority-enums"; +import { InternalCertificateAuthoritySchema } from "@app/services/certificate-authority/internal/internal-certificate-authority-schemas"; + +const CertificateAuthoritySchema = z.discriminatedUnion("type", [ + InternalCertificateAuthoritySchema, + AcmeCertificateAuthoritySchema, + AzureAdCsCertificateAuthoritySchema +]); + +export const registerGeneralCertificateAuthorityRouter = async (server: FastifyZodProvider) => { + server.route({ + method: "GET", + url: "/", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Get Certificate Authorities", + querystring: z.object({ + projectId: z.string() + }), + response: { + 200: z.object({ + certificateAuthorities: CertificateAuthoritySchema.array() + }) + } + }, + handler: async (req) => { + const internalCas = await server.services.certificateAuthority.listCertificateAuthoritiesByProjectId( + { + projectId: req.query.projectId, + type: CaType.INTERNAL + }, + req.permission + ); + + const acmeCas = await server.services.certificateAuthority.listCertificateAuthoritiesByProjectId( + { + projectId: req.query.projectId, + type: CaType.ACME + }, + req.permission + ); + + const azureAdCsCas = await server.services.certificateAuthority.listCertificateAuthoritiesByProjectId( + { + projectId: req.query.projectId, + type: CaType.AZURE_AD_CS + }, + req.permission + ); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: req.query.projectId, + event: { + type: EventType.GET_CAS, + metadata: { + caIds: [ + ...(internalCas ?? []).map((ca) => ca.id), + ...(acmeCas ?? []).map((ca) => ca.id), + ...(azureAdCsCas ?? []).map((ca) => ca.id) + ] + } + } + }); + + return { + certificateAuthorities: [...(internalCas ?? []), ...(acmeCas ?? []), ...(azureAdCsCas ?? [])] + }; + } + }); +}; diff --git a/backend/src/server/routes/v1/certificate-authority-routers/internal-certificate-authority-router.ts b/backend/src/server/routes/v1/certificate-authority-routers/internal-certificate-authority-router.ts index 61dc3ed57..73e3bde54 100644 --- a/backend/src/server/routes/v1/certificate-authority-routers/internal-certificate-authority-router.ts +++ b/backend/src/server/routes/v1/certificate-authority-routers/internal-certificate-authority-router.ts @@ -1,4 +1,12 @@ -import { CaType } from "@app/services/certificate-authority/certificate-authority-enums"; +import { z } from "zod"; + +import { EventType } from "@app/ee/services/audit-log/audit-log-types"; +import { ApiDocsTags, CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs"; +import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; +import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { AuthMode } from "@app/services/auth/auth-type"; +import { CaRenewalType, CaType } from "@app/services/certificate-authority/certificate-authority-enums"; +import { validateCaDateField } from "@app/services/certificate-authority/certificate-authority-validators"; import { CreateInternalCertificateAuthoritySchema, InternalCertificateAuthoritySchema, @@ -15,4 +23,406 @@ export const registerInternalCertificateAuthorityRouter = async (server: Fastify createSchema: CreateInternalCertificateAuthoritySchema, updateSchema: UpdateInternalCertificateAuthoritySchema }); + + server.route({ + method: "GET", + url: "/:caId/csr", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Get CA CSR", + params: z.object({ + caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CSR.caId) + }), + response: { + 200: z.object({ + csr: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CSR.csr) + }) + } + }, + handler: async (req) => { + const { ca, csr } = await server.services.internalCertificateAuthority.getCaCsr({ + caId: req.params.caId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.GET_CA_CSR, + metadata: { + caId: ca.id, + dn: ca.dn + } + } + }); + + return { + csr + }; + } + }); + + server.route({ + method: "POST", + url: "/:caId/renew", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Perform CA certificate renewal", + params: z.object({ + caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.caId) + }), + body: z.object({ + type: z.nativeEnum(CaRenewalType).describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.type), + notAfter: validateCaDateField.describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.notAfter) + }), + response: { + 200: z.object({ + certificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.certificate), + certificateChain: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.certificateChain), + serialNumber: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.serialNumber) + }) + } + }, + handler: async (req) => { + const { certificate, certificateChain, serialNumber, ca } = + await server.services.internalCertificateAuthority.renewCaCert({ + caId: req.params.caId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.RENEW_CA, + metadata: { + caId: ca.id, + dn: ca.dn + } + } + }); + + return { + certificate, + certificateChain, + serialNumber + }; + } + }); + + server.route({ + method: "GET", + url: "/:caId/ca-certificates", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Get list of past and current CA certificates for a CA", + params: z.object({ + caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.caId) + }), + response: { + 200: z.array( + z.object({ + certificate: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.certificate), + certificateChain: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.certificateChain), + serialNumber: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.serialNumber), + version: z.number().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.version) + }) + ) + } + }, + handler: async (req) => { + const { caCerts, ca } = await server.services.internalCertificateAuthority.getCaCerts({ + caId: req.params.caId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.GET_CA_CERTS, + metadata: { + caId: ca.id, + dn: ca.dn + } + } + }); + + return caCerts; + } + }); + + server.route({ + method: "GET", + url: "/:caId/certificate", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Get current CA cert and cert chain of a CA", + params: z.object({ + caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT.caId) + }), + response: { + 200: z.object({ + certificate: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CERT.certificate), + certificateChain: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CERT.certificateChain), + serialNumber: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CERT.serialNumber) + }) + } + }, + handler: async (req) => { + const { certificate, certificateChain, serialNumber, ca } = + await server.services.internalCertificateAuthority.getCaCert({ + caId: req.params.caId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.GET_CA_CERT, + metadata: { + caId: ca.id, + dn: ca.dn + } + } + }); + + return { + certificate, + certificateChain, + serialNumber + }; + } + }); + + server.route({ + method: "POST", + url: "/:caId/sign-intermediate", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Create intermediate CA certificate from parent CA", + params: z.object({ + caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.caId) + }), + body: z.object({ + csr: z.string().trim().min(1).describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.csr), + notBefore: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.notBefore), + notAfter: validateCaDateField.describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.notAfter), + maxPathLength: z.number().min(-1).default(-1).describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.maxPathLength) + }), + response: { + 200: z.object({ + certificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.certificate), + certificateChain: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.certificateChain), + issuingCaCertificate: z + .string() + .trim() + .describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.issuingCaCertificate), + serialNumber: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.serialNumber) + }) + } + }, + handler: async (req) => { + const { certificate, certificateChain, issuingCaCertificate, serialNumber, ca } = + await server.services.internalCertificateAuthority.signIntermediate({ + caId: req.params.caId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.SIGN_INTERMEDIATE, + metadata: { + caId: ca.id, + dn: ca.dn, + serialNumber + } + } + }); + + return { + certificate, + certificateChain, + issuingCaCertificate, + serialNumber + }; + } + }); + + server.route({ + method: "POST", + url: "/:caId/import-certificate", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Import certificate and chain to CA", + params: z.object({ + caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.IMPORT_CERT.caId) + }), + body: z.object({ + certificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.IMPORT_CERT.certificate), + certificateChain: z.string().trim().describe(CERTIFICATE_AUTHORITIES.IMPORT_CERT.certificateChain) + }), + response: { + 200: z.object({ + message: z.string().trim(), + caId: z.string().trim() + }) + } + }, + handler: async (req) => { + const { ca } = await server.services.internalCertificateAuthority.importCertToCa({ + caId: req.params.caId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.IMPORT_CA_CERT, + metadata: { + caId: ca.id, + dn: ca.dn + } + } + }); + + return { + message: "Successfully imported certificate to CA", + caId: req.params.caId + }; + } + }); + + server.route({ + method: "GET", + url: "/:caId/crls", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Get list of CRLs of the CA", + params: z.object({ + caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CRLS.caId) + }), + response: { + 200: z.array( + z.object({ + id: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CRLS.id), + crl: z.string().describe(CERTIFICATE_AUTHORITIES.GET_CRLS.crl) + }) + ) + } + }, + handler: async (req) => { + const { ca, crls } = await server.services.certificateAuthorityCrl.getCaCrls({ + caId: req.params.caId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.GET_CA_CRLS, + metadata: { + caId: ca.id, + dn: ca.dn + } + } + }); + + return crls; + } + }); + + // this endpoint will be used to serve the CA certificate when a client makes a request + // against the Authority Information Access CA Issuer URL + server.route({ + method: "GET", + url: "/:caId/certificates/:caCertId/der", + config: { + rateLimit: readLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + description: "Get DER-encoded certificate of CA", + params: z.object({ + caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caId), + caCertId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caCertId) + }), + response: { + 200: z.instanceof(Buffer) + } + }, + handler: async (req, res) => { + const caCert = await server.services.internalCertificateAuthority.getCaCertById(req.params); + + void res.header("Content-Type", "application/pkix-cert"); + + return Buffer.from(caCert.rawData); + } + }); }; diff --git a/backend/src/server/routes/v1/certificate-router.ts b/backend/src/server/routes/v1/certificate-router.ts index e8cdbb540..c2e322d69 100644 --- a/backend/src/server/routes/v1/certificate-router.ts +++ b/backend/src/server/routes/v1/certificate-router.ts @@ -4,24 +4,510 @@ import { z } from "zod"; import { CertificatesSchema } from "@app/db/schemas"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; -import { ApiDocsTags, CERTIFICATE_AUTHORITIES, CERTIFICATES } from "@app/lib/api-docs"; +import { ApiDocsTags, CERTIFICATES } from "@app/lib/api-docs"; import { ms } from "@app/lib/ms"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { addNoCacheHeaders } from "@app/server/lib/caching"; -import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; -import { CertExtendedKeyUsage, CertKeyUsage, CrlReason } from "@app/services/certificate/certificate-types"; import { - validateAltNamesField, - validateCaDateField -} from "@app/services/certificate-authority/certificate-authority-validators"; -import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types"; + ACMESANType, + CertificateOrderStatus, + CertKeyAlgorithm, + CertSignatureAlgorithm, + CrlReason +} from "@app/services/certificate/certificate-types"; +import { validateCaDateField } from "@app/services/certificate-authority/certificate-authority-validators"; +import { + CertExtendedKeyUsageType, + CertKeyUsageType, + CertSubjectAlternativeNameType +} from "@app/services/certificate-common/certificate-constants"; +import { extractCertificateRequestFromCSR } from "@app/services/certificate-common/certificate-csr-utils"; +import { mapEnumsForValidation } from "@app/services/certificate-common/certificate-utils"; +import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types"; +import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators"; + +import { booleanSchema } from "../sanitizedSchemas"; + +interface CertificateRequestForService { + commonName?: string; + keyUsages?: CertKeyUsageType[]; + extendedKeyUsages?: CertExtendedKeyUsageType[]; + altNames?: Array<{ + type: CertSubjectAlternativeNameType; + value: string; + }>; + validity: { + ttl: string; + }; + notBefore?: Date; + notAfter?: Date; + signatureAlgorithm?: string; + keyAlgorithm?: string; +} + +const validateTtlAndDateFields = (data: { notBefore?: string; notAfter?: string; ttl?: string }) => { + const hasDateFields = data.notBefore || data.notAfter; + const hasTtl = data.ttl; + return !(hasDateFields && hasTtl); +}; + +const validateDateOrder = (data: { notBefore?: string; notAfter?: string }) => { + if (data.notBefore && data.notAfter) { + const notBefore = new Date(data.notBefore); + const notAfter = new Date(data.notAfter); + return notBefore < notAfter; + } + return true; +}; + +export const registerCertificateRouter = async (server: FastifyZodProvider) => { + server.route({ + method: "POST", + url: "/issue-certificate", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + body: z + .object({ + profileId: z.string().uuid(), + commonName: validateTemplateRegexField.optional(), + ttl: z + .string() + .trim() + .min(1, "TTL cannot be empty") + .refine((val) => ms(val) > 0, "TTL must be a positive number"), + keyUsages: z.nativeEnum(CertKeyUsageType).array().optional(), + extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsageType).array().optional(), + notBefore: validateCaDateField.optional(), + notAfter: validateCaDateField.optional(), + altNames: z + .array( + z.object({ + type: z.nativeEnum(CertSubjectAlternativeNameType), + value: z.string().min(1, "SAN value cannot be empty") + }) + ) + .optional(), + signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm), + keyAlgorithm: z.nativeEnum(CertKeyAlgorithm), + removeRootsFromChain: booleanSchema.default(false).optional() + }) + .refine(validateTtlAndDateFields, { + message: + "Cannot specify both TTL and notBefore/notAfter. Use either TTL for duration-based validity or notBefore/notAfter for explicit date range." + }) + .refine(validateDateOrder, { + message: "notBefore must be earlier than notAfter" + }), + response: { + 200: z.object({ + certificate: z.string().trim(), + issuingCaCertificate: z.string().trim(), + certificateChain: z.string().trim(), + privateKey: z.string().trim().optional(), + serialNumber: z.string().trim(), + certificateId: z.string() + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const certificateRequestForService: CertificateRequestForService = { + commonName: req.body.commonName, + keyUsages: req.body.keyUsages, + extendedKeyUsages: req.body.extendedKeyUsages, + altNames: req.body.altNames, + validity: { + ttl: req.body.ttl + }, + notBefore: req.body.notBefore ? new Date(req.body.notBefore) : undefined, + notAfter: req.body.notAfter ? new Date(req.body.notAfter) : undefined, + signatureAlgorithm: req.body.signatureAlgorithm, + keyAlgorithm: req.body.keyAlgorithm + }; + + const mappedCertificateRequest = mapEnumsForValidation(certificateRequestForService); + + const data = await server.services.certificateV3.issueCertificateFromProfile({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + profileId: req.body.profileId, + certificateRequest: mappedCertificateRequest, + removeRootsFromChain: req.body.removeRootsFromChain + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: data.projectId, + event: { + type: EventType.ISSUE_CERTIFICATE_FROM_PROFILE, + metadata: { + certificateProfileId: req.body.profileId, + certificateId: data.certificateId, + commonName: req.body.commonName || "", + profileName: data.profileName + } + } + }); + + return data; + } + }); + + server.route({ + method: "POST", + url: "/sign-certificate", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + body: z + .object({ + profileId: z.string().uuid(), + csr: z.string().trim().min(1, "CSR cannot be empty").max(4096, "CSR cannot exceed 4096 characters"), + ttl: z + .string() + .trim() + .min(1, "TTL cannot be empty") + .refine((val) => ms(val) > 0, "TTL must be a positive number"), + notBefore: validateCaDateField.optional(), + notAfter: validateCaDateField.optional(), + removeRootsFromChain: booleanSchema.default(false).optional() + }) + .refine(validateTtlAndDateFields, { + message: + "Cannot specify both TTL and notBefore/notAfter. Use either TTL for duration-based validity or notBefore/notAfter for explicit date range." + }) + .refine(validateDateOrder, { + message: "notBefore must be earlier than notAfter" + }), + response: { + 200: z.object({ + certificate: z.string().trim(), + issuingCaCertificate: z.string().trim(), + certificateChain: z.string().trim(), + serialNumber: z.string().trim(), + certificateId: z.string() + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const certificateRequest = extractCertificateRequestFromCSR(req.body.csr); + + const data = await server.services.certificateV3.signCertificateFromProfile({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + profileId: req.body.profileId, + csr: req.body.csr, + validity: { + ttl: req.body.ttl + }, + notBefore: req.body.notBefore ? new Date(req.body.notBefore) : undefined, + notAfter: req.body.notAfter ? new Date(req.body.notAfter) : undefined, + enrollmentType: EnrollmentType.API, + removeRootsFromChain: req.body.removeRootsFromChain + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: data.projectId, + event: { + type: EventType.SIGN_CERTIFICATE_FROM_PROFILE, + metadata: { + certificateProfileId: req.body.profileId, + certificateId: data.certificateId, + profileName: data.profileName, + commonName: certificateRequest.commonName || "" + } + } + }); + + return data; + } + }); + + server.route({ + method: "POST", + url: "/order-certificate", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + body: z + .object({ + profileId: z.string().uuid(), + subjectAlternativeNames: z + .array( + z.object({ + type: z.nativeEnum(ACMESANType), + value: z + .string() + .trim() + .min(1, "SAN value cannot be empty") + .max(255, "SAN value must be less than 255 characters") + }) + ) + .min(1, "At least one subject alternative name must be provided"), + ttl: z + .string() + .trim() + .min(1, "TTL cannot be empty") + .refine((val) => ms(val) > 0, "TTL must be a positive number"), + keyUsages: z.nativeEnum(CertKeyUsageType).array().optional(), + extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsageType).array().optional(), + notBefore: validateCaDateField.optional(), + notAfter: validateCaDateField.optional(), + commonName: validateTemplateRegexField.optional(), + signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm), + keyAlgorithm: z.nativeEnum(CertKeyAlgorithm), + removeRootsFromChain: booleanSchema.default(false).optional() + }) + .refine(validateTtlAndDateFields, { + message: + "Cannot specify both TTL and notBefore/notAfter. Use either TTL for duration-based validity or notBefore/notAfter for explicit date range." + }) + .refine(validateDateOrder, { + message: "notBefore must be earlier than notAfter" + }), + response: { + 200: z.object({ + orderId: z.string(), + status: z.nativeEnum(CertificateOrderStatus), + subjectAlternativeNames: z.array( + z.object({ + type: z.nativeEnum(ACMESANType), + value: z.string(), + status: z.nativeEnum(CertificateOrderStatus) + }) + ), + authorizations: z.array( + z.object({ + identifier: z.object({ + type: z.nativeEnum(ACMESANType), + value: z.string() + }), + status: z.nativeEnum(CertificateOrderStatus), + expires: z.string().optional(), + challenges: z.array( + z.object({ + type: z.string(), + status: z.nativeEnum(CertificateOrderStatus), + url: z.string(), + token: z.string() + }) + ) + }) + ), + finalize: z.string(), + certificate: z.string().optional() + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const data = await server.services.certificateV3.orderCertificateFromProfile({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + profileId: req.body.profileId, + certificateOrder: { + altNames: req.body.subjectAlternativeNames, + validity: { + ttl: req.body.ttl + }, + commonName: req.body.commonName, + keyUsages: req.body.keyUsages, + extendedKeyUsages: req.body.extendedKeyUsages, + notBefore: req.body.notBefore ? new Date(req.body.notBefore) : undefined, + notAfter: req.body.notAfter ? new Date(req.body.notAfter) : undefined, + signatureAlgorithm: req.body.signatureAlgorithm, + keyAlgorithm: req.body.keyAlgorithm + }, + removeRootsFromChain: req.body.removeRootsFromChain + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: data.projectId, + event: { + type: EventType.ORDER_CERTIFICATE_FROM_PROFILE, + metadata: { + certificateProfileId: req.body.profileId, + orderId: data.orderId, + profileName: data.profileName + } + } + }); + + return data; + } + }); + + server.route({ + method: "POST", + url: "/:certificateId/renew", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + params: z.object({ + certificateId: z.string().uuid() + }), + body: z + .object({ + removeRootsFromChain: booleanSchema.default(false).optional() + }) + .optional(), + response: { + 200: z.object({ + certificate: z.string().trim(), + issuingCaCertificate: z.string().trim(), + certificateChain: z.string().trim(), + privateKey: z.string().trim().optional(), + serialNumber: z.string().trim(), + certificateId: z.string() + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const data = await server.services.certificateV3.renewCertificate({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + certificateId: req.params.certificateId, + removeRootsFromChain: req.body?.removeRootsFromChain + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: data.projectId, + event: { + type: EventType.RENEW_CERTIFICATE, + metadata: { + originalCertificateId: req.params.certificateId, + newCertificateId: data.certificateId, + profileName: data.profileName, + commonName: data.commonName + } + } + }); + + return data; + } + }); + + server.route({ + method: "PATCH", + url: "/:certificateId/config", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + params: z.object({ + certificateId: z.string().uuid() + }), + body: z + .object({ + renewBeforeDays: z.number().int().min(1).max(30).optional(), + enableAutoRenewal: z.boolean().optional() + }) + .refine((data) => !(data.renewBeforeDays !== undefined && data.enableAutoRenewal === false), { + message: "Cannot specify both renewBeforeDays and enableAutoRenewal=false" + }), + response: { + 200: z.object({ + message: z.string(), + renewBeforeDays: z.number().optional() + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + if (req.body.enableAutoRenewal === false) { + const data = await server.services.certificateV3.disableRenewalConfig({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + certificateId: req.params.certificateId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: data.projectId, + event: { + type: EventType.DISABLE_CERTIFICATE_RENEWAL_CONFIG, + metadata: { + certificateId: req.params.certificateId, + commonName: data.commonName + } + } + }); + + return { + message: "Auto-renewal disabled successfully" + }; + } + + if (req.body.renewBeforeDays !== undefined) { + const data = await server.services.certificateV3.updateRenewalConfig({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + certificateId: req.params.certificateId, + renewBeforeDays: req.body.renewBeforeDays + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: data.projectId, + event: { + type: EventType.UPDATE_CERTIFICATE_RENEWAL_CONFIG, + metadata: { + certificateId: req.params.certificateId, + renewBeforeDays: req.body.renewBeforeDays.toString(), + commonName: data.commonName + } + } + }); + + return { + message: "Certificate configuration updated successfully", + renewBeforeDays: data.renewBeforeDays + }; + } + + return { + message: "No configuration changes requested" + }; + } + }); -export const registerCertRouter = async (server: FastifyZodProvider) => { server.route({ method: "GET", - url: "/:serialNumber", + url: "/:id", config: { rateLimit: readLimit }, @@ -31,7 +517,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { tags: [ApiDocsTags.PkiCertificates], description: "Get certificate", params: z.object({ - serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber) + id: z.string().trim().describe(CERTIFICATES.GET.id) }), response: { 200: z.object({ @@ -41,7 +527,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { }, handler: async (req) => { const { cert } = await server.services.certificate.getCert({ - serialNumber: req.params.serialNumber, + id: req.params.id, actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -67,10 +553,9 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { } }); - // TODO: In the future add support for other formats outside of PEM (such as DER). Adding a "format" query param may be best. server.route({ method: "GET", - url: "/:serialNumber/private-key", + url: "/:id/private-key", config: { rateLimit: readLimit }, @@ -80,7 +565,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { tags: [ApiDocsTags.PkiCertificates], description: "Get certificate private key", params: z.object({ - serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber) + id: z.string().trim().describe(CERTIFICATES.GET.id) }), response: { 200: z.string().trim() @@ -88,7 +573,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { }, handler: async (req, reply) => { const { cert, certPrivateKey } = await server.services.certificate.getCertPrivateKey({ - serialNumber: req.params.serialNumber, + id: req.params.id, actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -114,10 +599,9 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { } }); - // TODO: In the future add support for other formats outside of PEM (such as DER). Adding a "format" query param may be best. server.route({ method: "GET", - url: "/:serialNumber/bundle", + url: "/:id/bundle", config: { rateLimit: readLimit }, @@ -127,7 +611,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { tags: [ApiDocsTags.PkiCertificates], description: "Get certificate bundle including the certificate, chain, and private key.", params: z.object({ - serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber) + id: z.string().trim().describe(CERTIFICATES.GET_CERT.id) }), response: { 200: z.object({ @@ -141,7 +625,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { handler: async (req, reply) => { const { certificate, certificateChain, serialNumber, cert, privateKey } = await server.services.certificate.getCertBundle({ - serialNumber: req.params.serialNumber, + id: req.params.id, actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -172,120 +656,6 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { } }); - server.route({ - method: "POST", - url: "/issue-certificate", - config: { - rateLimit: writeLimit - }, - onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - schema: { - hide: false, - tags: [ApiDocsTags.PkiCertificates], - description: "Issue certificate", - body: z - .object({ - caId: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.caId), - certificateTemplateId: z - .string() - .trim() - .optional() - .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificateTemplateId), - pkiCollectionId: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.pkiCollectionId), - friendlyName: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.friendlyName), - commonName: z.string().trim().min(1).describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.commonName), - altNames: validateAltNamesField.describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.altNames), - ttl: z - .string() - .refine((val) => ms(val) > 0, "TTL must be a positive number") - .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.ttl), - notBefore: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.notBefore), - notAfter: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.notAfter), - keyUsages: z - .nativeEnum(CertKeyUsage) - .array() - .optional() - .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.keyUsages), - extendedKeyUsages: z - .nativeEnum(CertExtendedKeyUsage) - .array() - .optional() - .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.extendedKeyUsages) - }) - .refine( - (data) => { - const { ttl, notAfter } = data; - return (ttl !== undefined && notAfter === undefined) || (ttl === undefined && notAfter !== undefined); - }, - { - message: "Either ttl or notAfter must be present, but not both", - path: ["ttl", "notAfter"] - } - ) - .refine( - (data) => - (data.caId !== undefined && data.certificateTemplateId === undefined) || - (data.caId === undefined && data.certificateTemplateId !== undefined), - { - message: "Either CA ID or Certificate Template ID must be present, but not both", - path: ["caId", "certificateTemplateId"] - } - ), - response: { - 200: z.object({ - certificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificate), - issuingCaCertificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.issuingCaCertificate), - certificateChain: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificateChain), - privateKey: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.privateKey), - serialNumber: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.serialNumber) - }) - } - }, - handler: async (req) => { - const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } = - await server.services.internalCertificateAuthority.issueCertFromCa({ - actor: req.permission.type, - actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId, - ...req.body - }); - - await server.services.auditLog.createAuditLog({ - ...req.auditLogInfo, - projectId: ca.projectId, - event: { - type: EventType.ISSUE_CERT, - metadata: { - caId: ca.id, - dn: ca.dn, - serialNumber - } - } - }); - - await server.services.telemetry.sendPostHogEvents({ - event: PostHogEventTypes.IssueCert, - distinctId: getTelemetryDistinctId(req), - organizationId: req.permission.orgId, - properties: { - caId: req.body.caId, - certificateTemplateId: req.body.certificateTemplateId, - commonName: req.body.commonName, - ...req.auditLogInfo - } - }); - - return { - certificate, - certificateChain, - issuingCaCertificate, - privateKey, - serialNumber - }; - } - }); - server.route({ method: "POST", url: "/import-certificate", @@ -350,121 +720,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { server.route({ method: "POST", - url: "/sign-certificate", - config: { - rateLimit: writeLimit - }, - onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - schema: { - hide: false, - tags: [ApiDocsTags.PkiCertificates], - description: "Sign certificate", - body: z - .object({ - caId: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId), - certificateTemplateId: z - .string() - .trim() - .optional() - .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificateTemplateId), - pkiCollectionId: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.pkiCollectionId), - csr: z.string().trim().min(1).describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.csr), - friendlyName: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.friendlyName), - commonName: z.string().trim().min(1).optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.commonName), - altNames: validateAltNamesField.describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.altNames), - ttl: z - .string() - .refine((val) => ms(val) > 0, "TTL must be a positive number") - .describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.ttl), - notBefore: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notBefore), - notAfter: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notAfter), - keyUsages: z - .nativeEnum(CertKeyUsage) - .array() - .optional() - .describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.keyUsages), - extendedKeyUsages: z - .nativeEnum(CertExtendedKeyUsage) - .array() - .optional() - .describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.extendedKeyUsages) - }) - .refine( - (data) => { - const { ttl, notAfter } = data; - return (ttl !== undefined && notAfter === undefined) || (ttl === undefined && notAfter !== undefined); - }, - { - message: "Either ttl or notAfter must be present, but not both", - path: ["ttl", "notAfter"] - } - ) - .refine( - (data) => - (data.caId !== undefined && data.certificateTemplateId === undefined) || - (data.caId === undefined && data.certificateTemplateId !== undefined), - { - message: "Either CA ID or Certificate Template ID must be present, but not both", - path: ["caId", "certificateTemplateId"] - } - ), - response: { - 200: z.object({ - certificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.certificate), - issuingCaCertificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.issuingCaCertificate), - certificateChain: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificateChain), - serialNumber: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.serialNumber) - }) - } - }, - handler: async (req) => { - const { certificate, certificateChain, issuingCaCertificate, serialNumber, ca, commonName } = - await server.services.internalCertificateAuthority.signCertFromCa({ - isInternal: false, - actor: req.permission.type, - actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId, - ...req.body - }); - - await server.services.auditLog.createAuditLog({ - ...req.auditLogInfo, - projectId: ca.projectId, - event: { - type: EventType.SIGN_CERT, - metadata: { - caId: ca.id, - dn: ca.dn, - serialNumber - } - } - }); - - await server.services.telemetry.sendPostHogEvents({ - event: PostHogEventTypes.SignCert, - distinctId: getTelemetryDistinctId(req), - organizationId: req.permission.orgId, - properties: { - caId: req.body.caId, - certificateTemplateId: req.body.certificateTemplateId, - commonName, - ...req.auditLogInfo - } - }); - - return { - certificate: certificate.toString("pem"), - certificateChain, - issuingCaCertificate, - serialNumber - }; - } - }); - - server.route({ - method: "POST", - url: "/:serialNumber/revoke", + url: "/:id/revoke", config: { rateLimit: writeLimit }, @@ -474,7 +730,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { tags: [ApiDocsTags.PkiCertificates], description: "Revoke", params: z.object({ - serialNumber: z.string().trim().describe(CERTIFICATES.REVOKE.serialNumber) + id: z.string().trim().describe(CERTIFICATES.REVOKE.id) }), body: z.object({ revocationReason: z.nativeEnum(CrlReason).describe(CERTIFICATES.REVOKE.revocationReason) @@ -489,7 +745,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { }, handler: async (req) => { const { revokedAt, cert, ca } = await server.services.certificate.revokeCert({ - serialNumber: req.params.serialNumber, + id: req.params.id, actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -512,7 +768,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { return { message: "Successfully revoked certificate", - serialNumber: req.params.serialNumber, + serialNumber: cert.serialNumber, revokedAt }; } @@ -520,7 +776,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { server.route({ method: "DELETE", - url: "/:serialNumber", + url: "/:id", config: { rateLimit: writeLimit }, @@ -530,7 +786,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { tags: [ApiDocsTags.PkiCertificates], description: "Delete certificate", params: z.object({ - serialNumber: z.string().trim().describe(CERTIFICATES.DELETE.serialNumber) + id: z.string().trim().describe(CERTIFICATES.DELETE.id) }), response: { 200: z.object({ @@ -540,7 +796,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { }, handler: async (req) => { const { deletedCert } = await server.services.certificate.deleteCert({ - serialNumber: req.params.serialNumber, + id: req.params.id, actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -568,7 +824,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { server.route({ method: "GET", - url: "/:serialNumber/certificate", + url: "/:id/certificate", config: { rateLimit: readLimit }, @@ -578,7 +834,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { tags: [ApiDocsTags.PkiCertificates], description: "Get certificate body of certificate", params: z.object({ - serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber) + id: z.string().trim().describe(CERTIFICATES.GET_CERT.id) }), response: { 200: z.object({ @@ -590,7 +846,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { }, handler: async (req) => { const { certificate, certificateChain, serialNumber, cert } = await server.services.certificate.getCertBody({ - serialNumber: req.params.serialNumber, + id: req.params.id, actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -620,7 +876,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { server.route({ method: "POST", - url: "/:serialNumber/pkcs12", + url: "/:id/pkcs12", config: { rateLimit: writeLimit }, @@ -630,7 +886,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { tags: [ApiDocsTags.PkiCertificates], description: "Download certificate in PKCS12 format", params: z.object({ - serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber) + id: z.string().trim().describe(CERTIFICATES.GET.id) }), body: z.object({ password: z @@ -645,7 +901,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { }, handler: async (req, reply) => { const { pkcs12Data, cert } = await server.services.certificate.getCertPkcs12({ - serialNumber: req.params.serialNumber, + id: req.params.id, password: req.body.password, alias: req.body.alias, actor: req.permission.type, @@ -671,7 +927,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => { reply.header("Content-Type", "application/octet-stream"); reply.header( "Content-Disposition", - `attachment; filename="certificate-${req.params.serialNumber.replace(new RE2("[^\\w.-]", "g"), "_")}.p12"` + `attachment; filename="certificate-${cert.serialNumber?.replace(new RE2("[^\\w.-]", "g"), "_")}.p12"` ); return pkcs12Data; diff --git a/backend/src/server/routes/v1/certificate-template-router.ts b/backend/src/server/routes/v1/certificate-template-router.ts index 5ff0e39c0..499d0b98e 100644 --- a/backend/src/server/routes/v1/certificate-template-router.ts +++ b/backend/src/server/routes/v1/certificate-template-router.ts @@ -1,28 +1,239 @@ +import RE2 from "re2"; import { z } from "zod"; -import { CertificateTemplateEstConfigsSchema } from "@app/db/schemas"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; -import { ApiDocsTags, CERTIFICATE_TEMPLATES } from "@app/lib/api-docs"; -import { ms } from "@app/lib/ms"; +import { ApiDocsTags } from "@app/lib/api-docs"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; -import { slugSchema } from "@app/server/lib/schemas"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; -import { CertExtendedKeyUsage, CertKeyUsage } from "@app/services/certificate/certificate-types"; -import { sanitizedCertificateTemplate } from "@app/services/certificate-template/certificate-template-schema"; -import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators"; +import { + CertExtendedKeyUsageType, + CertKeyUsageType, + CertSubjectAlternativeNameType, + CertSubjectAttributeType +} from "@app/services/certificate-common/certificate-constants"; +import { certificateTemplateV2ResponseSchema } from "@app/services/certificate-template-v2/certificate-template-v2-schemas"; -const sanitizedEstConfig = CertificateTemplateEstConfigsSchema.pick({ - id: true, - certificateTemplateId: true, - isEnabled: true, - disableBootstrapCertValidation: true +const attributeTypeSchema = z.nativeEnum(CertSubjectAttributeType); +const sanTypeSchema = z.nativeEnum(CertSubjectAlternativeNameType); + +const templateV2SubjectSchema = z + .object({ + type: attributeTypeSchema, + allowed: z.array(z.string()).optional(), + required: z.array(z.string()).optional(), + denied: z.array(z.string()).optional() + }) + .refine( + (data) => { + if (!data.allowed && !data.required && !data.denied) { + return false; + } + return true; + }, + { + message: "Subject attribute must have at least one allowed, required, or denied value" + } + ); + +const templateV2KeyUsagesSchema = z + .object({ + allowed: z.array(z.nativeEnum(CertKeyUsageType)).optional(), + required: z.array(z.nativeEnum(CertKeyUsageType)).optional(), + denied: z.array(z.nativeEnum(CertKeyUsageType)).optional() + }) + .refine( + (data) => { + if (!data.allowed && !data.required && !data.denied) { + return false; + } + return true; + }, + { + message: "Key usages must have at least one allowed, required, or denied value" + } + ); + +const templateV2ExtendedKeyUsagesSchema = z + .object({ + allowed: z.array(z.nativeEnum(CertExtendedKeyUsageType)).optional(), + required: z.array(z.nativeEnum(CertExtendedKeyUsageType)).optional(), + denied: z.array(z.nativeEnum(CertExtendedKeyUsageType)).optional() + }) + .refine( + (data) => { + if (!data.allowed && !data.required && !data.denied) { + return false; + } + return true; + }, + { + message: "Extended key usages must have at least one allowed, required, or denied value" + } + ); + +const templateV2SanSchema = z + .object({ + type: sanTypeSchema, + allowed: z.array(z.string()).optional(), + required: z.array(z.string()).optional(), + denied: z.array(z.string()).optional() + }) + .refine( + (data) => { + if (!data.allowed && !data.required && !data.denied) { + return false; + } + return true; + }, + { + message: "SAN must have at least one allowed, required, or denied value" + } + ); + +const templateV2ValiditySchema = z.object({ + max: z + .string() + .refine( + (val) => { + if (!val) return true; + if (val.length < 2) return false; + const unit = val.slice(-1); + const number = val.slice(0, -1); + const digitRegex = new RE2("^\\d+$"); + return ["d", "h", "m", "y"].includes(unit) && digitRegex.test(number); + }, + { + message: "Max validity must be in format like '365d', '12m', '1y', or '24h'" + } + ) + .optional() +}); + +const templateV2AlgorithmsSchema = z.object({ + signature: z.array(z.string()).min(1, "At least one signature algorithm must be provided").optional(), + keyAlgorithm: z.array(z.string()).min(1, "At least one key algorithm must be provided").optional() +}); + +const createCertificateTemplateV2Schema = z.object({ + projectId: z.string().min(1), + name: z.string().min(1).max(255, "Name must be between 1 and 255 characters"), + description: z.string().max(1000).optional(), + subject: z.array(templateV2SubjectSchema).optional(), + sans: z.array(templateV2SanSchema).optional(), + keyUsages: templateV2KeyUsagesSchema.optional(), + extendedKeyUsages: templateV2ExtendedKeyUsagesSchema.optional(), + algorithms: templateV2AlgorithmsSchema.optional(), + validity: templateV2ValiditySchema.optional() +}); + +const updateCertificateTemplateV2Schema = z.object({ + name: z.string().min(1).max(255, "Name must be between 1 and 255 characters").optional(), + description: z.string().max(1000).optional(), + subject: z.array(templateV2SubjectSchema).optional(), + sans: z.array(templateV2SanSchema).optional(), + keyUsages: templateV2KeyUsagesSchema.optional(), + extendedKeyUsages: templateV2ExtendedKeyUsagesSchema.optional(), + algorithms: templateV2AlgorithmsSchema.optional(), + validity: templateV2ValiditySchema.optional() }); export const registerCertificateTemplateRouter = async (server: FastifyZodProvider) => { + server.route({ + method: "POST", + url: "/", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + body: createCertificateTemplateV2Schema, + response: { + 200: z.object({ + certificateTemplate: certificateTemplateV2ResponseSchema + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const { projectId, ...data } = req.body; + const certificateTemplate = await server.services.certificateTemplateV2.createTemplateV2({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod!, + actorOrgId: req.permission.orgId, + projectId, + data + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId, + event: { + type: EventType.CREATE_CERTIFICATE_TEMPLATE, + metadata: { + certificateTemplateId: certificateTemplate.id, + name: certificateTemplate.name, + projectId: certificateTemplate.projectId + } + } + }); + + return { certificateTemplate }; + } + }); + server.route({ method: "GET", - url: "/:certificateTemplateId", + url: "/", + config: { + rateLimit: readLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + querystring: z.object({ + projectId: z.string().min(1), + offset: z.coerce.number().min(0).default(0), + limit: z.coerce.number().min(1).max(100).default(20), + search: z.string().optional() + }), + response: { + 200: z.object({ + certificateTemplates: certificateTemplateV2ResponseSchema.array(), + totalCount: z.number() + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const { templates, totalCount } = await server.services.certificateTemplateV2.listTemplatesV2({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod!, + actorOrgId: req.permission.orgId, + ...req.query + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: req.query.projectId, + event: { + type: EventType.LIST_CERTIFICATE_TEMPLATES, + metadata: { + projectId: req.query.projectId + } + } + }); + + return { certificateTemplates: templates, totalCount }; + } + }); + + server.route({ + method: "GET", + url: "/:id", config: { rateLimit: readLimit }, @@ -30,20 +241,22 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid hide: false, tags: [ApiDocsTags.PkiCertificateTemplates], params: z.object({ - certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.GET.certificateTemplateId) + id: z.string().uuid() }), response: { - 200: sanitizedCertificateTemplate + 200: z.object({ + certificateTemplate: certificateTemplateV2ResponseSchema + }) } }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const certificateTemplate = await server.services.certificateTemplate.getCertTemplate({ - id: req.params.certificateTemplateId, + const certificateTemplate = await server.services.certificateTemplateV2.getTemplateV2ById({ actor: req.permission.type, actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId + actorAuthMethod: req.permission.authMethod!, + actorOrgId: req.permission.orgId, + templateId: req.params.id }); await server.services.auditLog.createAuditLog({ @@ -58,125 +271,38 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid } }); - return certificateTemplate; - } - }); - - server.route({ - method: "POST", - url: "/", - config: { - rateLimit: writeLimit - }, - schema: { - hide: false, - tags: [ApiDocsTags.PkiCertificateTemplates], - body: z.object({ - caId: z.string().describe(CERTIFICATE_TEMPLATES.CREATE.caId), - pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.CREATE.pkiCollectionId), - name: slugSchema().describe(CERTIFICATE_TEMPLATES.CREATE.name), - commonName: validateTemplateRegexField.describe(CERTIFICATE_TEMPLATES.CREATE.commonName), - subjectAlternativeName: validateTemplateRegexField.describe( - CERTIFICATE_TEMPLATES.CREATE.subjectAlternativeName - ), - ttl: z - .string() - .refine((val) => ms(val) > 0, "TTL must be a positive number") - .describe(CERTIFICATE_TEMPLATES.CREATE.ttl), - keyUsages: z - .nativeEnum(CertKeyUsage) - .array() - .optional() - .default([CertKeyUsage.DIGITAL_SIGNATURE, CertKeyUsage.KEY_ENCIPHERMENT]) - .describe(CERTIFICATE_TEMPLATES.CREATE.keyUsages), - extendedKeyUsages: z - .nativeEnum(CertExtendedKeyUsage) - .array() - .optional() - .default([]) - .describe(CERTIFICATE_TEMPLATES.CREATE.extendedKeyUsages) - }), - response: { - 200: sanitizedCertificateTemplate - } - }, - onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - handler: async (req) => { - const certificateTemplate = await server.services.certificateTemplate.createCertTemplate({ - actor: req.permission.type, - actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId, - ...req.body - }); - - await server.services.auditLog.createAuditLog({ - ...req.auditLogInfo, - projectId: certificateTemplate.projectId, - event: { - type: EventType.CREATE_CERTIFICATE_TEMPLATE, - metadata: { - certificateTemplateId: certificateTemplate.id, - caId: certificateTemplate.caId, - pkiCollectionId: certificateTemplate.pkiCollectionId as string, - name: certificateTemplate.name, - commonName: certificateTemplate.commonName, - subjectAlternativeName: certificateTemplate.subjectAlternativeName, - ttl: certificateTemplate.ttl, - projectId: certificateTemplate.projectId - } - } - }); - - return certificateTemplate; + return { certificateTemplate }; } }); server.route({ method: "PATCH", - url: "/:certificateTemplateId", + url: "/:id", config: { rateLimit: writeLimit }, schema: { hide: false, tags: [ApiDocsTags.PkiCertificateTemplates], - body: z.object({ - caId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.caId), - pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.pkiCollectionId), - name: slugSchema().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.name), - commonName: validateTemplateRegexField.optional().describe(CERTIFICATE_TEMPLATES.UPDATE.commonName), - subjectAlternativeName: validateTemplateRegexField - .optional() - .describe(CERTIFICATE_TEMPLATES.UPDATE.subjectAlternativeName), - ttl: z - .string() - .refine((val) => ms(val) > 0, "TTL must be a positive number") - .optional() - .describe(CERTIFICATE_TEMPLATES.UPDATE.ttl), - keyUsages: z.nativeEnum(CertKeyUsage).array().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.keyUsages), - extendedKeyUsages: z - .nativeEnum(CertExtendedKeyUsage) - .array() - .optional() - .describe(CERTIFICATE_TEMPLATES.UPDATE.extendedKeyUsages) - }), params: z.object({ - certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.UPDATE.certificateTemplateId) + id: z.string().uuid() }), + body: updateCertificateTemplateV2Schema, response: { - 200: sanitizedCertificateTemplate + 200: z.object({ + certificateTemplate: certificateTemplateV2ResponseSchema + }) } }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const certificateTemplate = await server.services.certificateTemplate.updateCertTemplate({ - ...req.body, - id: req.params.certificateTemplateId, + const certificateTemplate = await server.services.certificateTemplateV2.updateTemplateV2({ actor: req.permission.type, actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId + actorAuthMethod: req.permission.authMethod!, + actorOrgId: req.permission.orgId, + templateId: req.params.id, + data: req.body }); await server.services.auditLog.createAuditLog({ @@ -186,23 +312,18 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid type: EventType.UPDATE_CERTIFICATE_TEMPLATE, metadata: { certificateTemplateId: certificateTemplate.id, - name: certificateTemplate.name, - caId: certificateTemplate.caId, - pkiCollectionId: certificateTemplate.pkiCollectionId as string, - commonName: certificateTemplate.commonName, - subjectAlternativeName: certificateTemplate.subjectAlternativeName, - ttl: certificateTemplate.ttl + name: certificateTemplate.name } } }); - return certificateTemplate; + return { certificateTemplate }; } }); server.route({ method: "DELETE", - url: "/:certificateTemplateId", + url: "/:id", config: { rateLimit: writeLimit }, @@ -210,20 +331,22 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid hide: false, tags: [ApiDocsTags.PkiCertificateTemplates], params: z.object({ - certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId) + id: z.string().uuid() }), response: { - 200: sanitizedCertificateTemplate + 200: z.object({ + certificateTemplate: certificateTemplateV2ResponseSchema + }) } }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { - const certificateTemplate = await server.services.certificateTemplate.deleteCertTemplate({ - id: req.params.certificateTemplateId, + const certificateTemplate = await server.services.certificateTemplateV2.deleteTemplateV2({ actor: req.permission.type, actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId + actorAuthMethod: req.permission.authMethod!, + actorOrgId: req.permission.orgId, + templateId: req.params.id }); await server.services.auditLog.createAuditLog({ @@ -238,158 +361,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid } }); - return certificateTemplate; - } - }); - - server.route({ - method: "POST", - url: "/:certificateTemplateId/est-config", - config: { - rateLimit: writeLimit - }, - onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - schema: { - hide: false, - tags: [ApiDocsTags.PkiCertificateTemplates], - description: "Create Certificate Template EST configuration", - params: z.object({ - certificateTemplateId: z.string().trim() - }), - body: z - .object({ - caChain: z.string().trim().optional(), - passphrase: z.string().min(1), - isEnabled: z.boolean().default(true), - disableBootstrapCertValidation: z.boolean().default(false) - }) - .refine( - ({ caChain, disableBootstrapCertValidation }) => - disableBootstrapCertValidation || (!disableBootstrapCertValidation && caChain), - "CA chain is required" - ), - response: { - 200: sanitizedEstConfig - } - }, - handler: async (req) => { - const estConfig = await server.services.certificateTemplate.createEstConfiguration({ - certificateTemplateId: req.params.certificateTemplateId, - actor: req.permission.type, - actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId, - ...req.body - }); - - await server.services.auditLog.createAuditLog({ - ...req.auditLogInfo, - projectId: estConfig.projectId, - event: { - type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG, - metadata: { - certificateTemplateId: estConfig.certificateTemplateId, - isEnabled: estConfig.isEnabled as boolean - } - } - }); - - return estConfig; - } - }); - - server.route({ - method: "PATCH", - url: "/:certificateTemplateId/est-config", - config: { - rateLimit: writeLimit - }, - onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - schema: { - hide: false, - tags: [ApiDocsTags.PkiCertificateTemplates], - description: "Update Certificate Template EST configuration", - params: z.object({ - certificateTemplateId: z.string().trim() - }), - body: z.object({ - caChain: z.string().trim().optional(), - passphrase: z.string().min(1).optional(), - disableBootstrapCertValidation: z.boolean().optional(), - isEnabled: z.boolean().optional() - }), - response: { - 200: sanitizedEstConfig - } - }, - handler: async (req) => { - const estConfig = await server.services.certificateTemplate.updateEstConfiguration({ - certificateTemplateId: req.params.certificateTemplateId, - actor: req.permission.type, - actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId, - ...req.body - }); - - await server.services.auditLog.createAuditLog({ - ...req.auditLogInfo, - projectId: estConfig.projectId, - event: { - type: EventType.UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG, - metadata: { - certificateTemplateId: estConfig.certificateTemplateId, - isEnabled: estConfig.isEnabled as boolean - } - } - }); - - return estConfig; - } - }); - - server.route({ - method: "GET", - url: "/:certificateTemplateId/est-config", - config: { - rateLimit: readLimit - }, - onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - schema: { - hide: false, - tags: [ApiDocsTags.PkiCertificateTemplates], - description: "Get Certificate Template EST configuration", - params: z.object({ - certificateTemplateId: z.string().trim() - }), - response: { - 200: sanitizedEstConfig.extend({ - caChain: z.string() - }) - } - }, - handler: async (req) => { - const estConfig = await server.services.certificateTemplate.getEstConfiguration({ - isInternal: false, - certificateTemplateId: req.params.certificateTemplateId, - actor: req.permission.type, - actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId - }); - - await server.services.auditLog.createAuditLog({ - ...req.auditLogInfo, - projectId: estConfig.projectId, - event: { - type: EventType.GET_CERTIFICATE_TEMPLATE_EST_CONFIG, - metadata: { - certificateTemplateId: estConfig.certificateTemplateId - } - } - }); - - return estConfig; + return { certificateTemplate }; } }); }; diff --git a/backend/src/server/routes/v1/deprecated-certificate-router.ts b/backend/src/server/routes/v1/deprecated-certificate-router.ts new file mode 100644 index 000000000..955407e4c --- /dev/null +++ b/backend/src/server/routes/v1/deprecated-certificate-router.ts @@ -0,0 +1,680 @@ +/* eslint-disable @typescript-eslint/no-floating-promises */ +import RE2 from "re2"; +import { z } from "zod"; + +import { CertificatesSchema } from "@app/db/schemas"; +import { EventType } from "@app/ee/services/audit-log/audit-log-types"; +import { ApiDocsTags, CERTIFICATE_AUTHORITIES, CERTIFICATES } from "@app/lib/api-docs"; +import { ms } from "@app/lib/ms"; +import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; +import { addNoCacheHeaders } from "@app/server/lib/caching"; +import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; +import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { AuthMode } from "@app/services/auth/auth-type"; +import { CertExtendedKeyUsage, CertKeyUsage, CrlReason } from "@app/services/certificate/certificate-types"; +import { + validateAltNamesField, + validateCaDateField +} from "@app/services/certificate-authority/certificate-authority-validators"; +import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types"; + +export const registerDeprecatedCertRouter = async (server: FastifyZodProvider) => { + server.route({ + method: "GET", + url: "/:serialNumber", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Get certificate", + params: z.object({ + serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber) + }), + response: { + 200: z.object({ + certificate: CertificatesSchema + }) + } + }, + handler: async (req) => { + const { cert } = await server.services.certificate.getCert({ + serialNumber: req.params.serialNumber, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: cert.projectId, + event: { + type: EventType.GET_CERT, + metadata: { + certId: cert.id, + cn: cert.commonName, + serialNumber: cert.serialNumber + } + } + }); + + return { + certificate: cert + }; + } + }); + + // TODO: In the future add support for other formats outside of PEM (such as DER). Adding a "format" query param may be best. + server.route({ + method: "GET", + url: "/:serialNumber/private-key", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Get certificate private key", + params: z.object({ + serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber) + }), + response: { + 200: z.string().trim() + } + }, + handler: async (req, reply) => { + const { cert, certPrivateKey } = await server.services.certificate.getCertPrivateKey({ + serialNumber: req.params.serialNumber, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: cert.projectId, + event: { + type: EventType.GET_CERT_PRIVATE_KEY, + metadata: { + certId: cert.id, + cn: cert.commonName, + serialNumber: cert.serialNumber + } + } + }); + + addNoCacheHeaders(reply); + + return certPrivateKey; + } + }); + + // TODO: In the future add support for other formats outside of PEM (such as DER). Adding a "format" query param may be best. + server.route({ + method: "GET", + url: "/:serialNumber/bundle", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Get certificate bundle including the certificate, chain, and private key.", + params: z.object({ + serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber) + }), + response: { + 200: z.object({ + certificate: z.string().trim().describe(CERTIFICATES.GET_CERT.certificate), + certificateChain: z.string().trim().nullable().describe(CERTIFICATES.GET_CERT.certificateChain), + privateKey: z.string().trim().nullable().describe(CERTIFICATES.GET_CERT.privateKey), + serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumberRes) + }) + } + }, + handler: async (req, reply) => { + const { certificate, certificateChain, serialNumber, cert, privateKey } = + await server.services.certificate.getCertBundle({ + serialNumber: req.params.serialNumber, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: cert.projectId, + event: { + type: EventType.GET_CERT_BUNDLE, + metadata: { + certId: cert.id, + cn: cert.commonName, + serialNumber: cert.serialNumber + } + } + }); + + addNoCacheHeaders(reply); + + return { + certificate, + certificateChain, + serialNumber, + privateKey + }; + } + }); + + server.route({ + method: "POST", + url: "/issue-certificate", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Issue certificate", + body: z + .object({ + caId: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.caId), + certificateTemplateId: z + .string() + .trim() + .optional() + .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificateTemplateId), + pkiCollectionId: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.pkiCollectionId), + friendlyName: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.friendlyName), + commonName: z.string().trim().min(1).describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.commonName), + altNames: validateAltNamesField.describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.altNames), + ttl: z + .string() + .refine((val) => ms(val) > 0, "TTL must be a positive number") + .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.ttl), + notBefore: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.notBefore), + notAfter: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.notAfter), + keyUsages: z + .nativeEnum(CertKeyUsage) + .array() + .optional() + .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.keyUsages), + extendedKeyUsages: z + .nativeEnum(CertExtendedKeyUsage) + .array() + .optional() + .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.extendedKeyUsages) + }) + .refine( + (data) => { + const { ttl, notAfter } = data; + return (ttl !== undefined && notAfter === undefined) || (ttl === undefined && notAfter !== undefined); + }, + { + message: "Either ttl or notAfter must be present, but not both", + path: ["ttl", "notAfter"] + } + ) + .refine( + (data) => + (data.caId !== undefined && data.certificateTemplateId === undefined) || + (data.caId === undefined && data.certificateTemplateId !== undefined), + { + message: "Either CA ID or Certificate Template ID must be present, but not both", + path: ["caId", "certificateTemplateId"] + } + ), + response: { + 200: z.object({ + certificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificate), + issuingCaCertificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.issuingCaCertificate), + certificateChain: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificateChain), + privateKey: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.privateKey), + serialNumber: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.serialNumber) + }) + } + }, + handler: async (req) => { + const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } = + await server.services.internalCertificateAuthority.issueCertFromCa({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.ISSUE_CERT, + metadata: { + caId: ca.id, + dn: ca.dn, + serialNumber + } + } + }); + + await server.services.telemetry.sendPostHogEvents({ + event: PostHogEventTypes.IssueCert, + distinctId: getTelemetryDistinctId(req), + organizationId: req.permission.orgId, + properties: { + caId: req.body.caId, + certificateTemplateId: req.body.certificateTemplateId, + commonName: req.body.commonName, + ...req.auditLogInfo + } + }); + + return { + certificate, + certificateChain, + issuingCaCertificate, + privateKey, + serialNumber + }; + } + }); + + server.route({ + method: "POST", + url: "/import-certificate", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Import certificate", + body: z.object({ + projectSlug: z.string().trim().min(1).describe(CERTIFICATES.IMPORT.projectSlug), + + certificatePem: z.string().trim().min(1).describe(CERTIFICATES.IMPORT.certificatePem), + privateKeyPem: z.string().trim().min(1).describe(CERTIFICATES.IMPORT.privateKeyPem), + chainPem: z.string().trim().min(1).describe(CERTIFICATES.IMPORT.chainPem), + + friendlyName: z.string().trim().optional().describe(CERTIFICATES.IMPORT.friendlyName), + pkiCollectionId: z.string().trim().optional().describe(CERTIFICATES.IMPORT.pkiCollectionId) + }), + response: { + 200: z.object({ + certificate: z.string().trim().describe(CERTIFICATES.IMPORT.certificate), + certificateChain: z.string().trim().describe(CERTIFICATES.IMPORT.certificateChain), + privateKey: z.string().trim().describe(CERTIFICATES.IMPORT.privateKey), + serialNumber: z.string().trim().describe(CERTIFICATES.IMPORT.serialNumber) + }) + } + }, + handler: async (req) => { + const { certificate, certificateChain, privateKey, serialNumber, cert } = + await server.services.certificate.importCert({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: cert.projectId, + event: { + type: EventType.IMPORT_CERT, + metadata: { + certId: cert.id, + cn: cert.commonName, + serialNumber + } + } + }); + + return { + certificate, + certificateChain, + privateKey, + serialNumber + }; + } + }); + + server.route({ + method: "POST", + url: "/sign-certificate", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Sign certificate", + body: z + .object({ + caId: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId), + certificateTemplateId: z + .string() + .trim() + .optional() + .describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificateTemplateId), + pkiCollectionId: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.pkiCollectionId), + csr: z.string().trim().min(1).describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.csr), + friendlyName: z.string().trim().optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.friendlyName), + commonName: z.string().trim().min(1).optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.commonName), + altNames: validateAltNamesField.describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.altNames), + ttl: z + .string() + .refine((val) => ms(val) > 0, "TTL must be a positive number") + .describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.ttl), + notBefore: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notBefore), + notAfter: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notAfter), + keyUsages: z + .nativeEnum(CertKeyUsage) + .array() + .optional() + .describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.keyUsages), + extendedKeyUsages: z + .nativeEnum(CertExtendedKeyUsage) + .array() + .optional() + .describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.extendedKeyUsages) + }) + .refine( + (data) => { + const { ttl, notAfter } = data; + return (ttl !== undefined && notAfter === undefined) || (ttl === undefined && notAfter !== undefined); + }, + { + message: "Either ttl or notAfter must be present, but not both", + path: ["ttl", "notAfter"] + } + ) + .refine( + (data) => + (data.caId !== undefined && data.certificateTemplateId === undefined) || + (data.caId === undefined && data.certificateTemplateId !== undefined), + { + message: "Either CA ID or Certificate Template ID must be present, but not both", + path: ["caId", "certificateTemplateId"] + } + ), + response: { + 200: z.object({ + certificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.certificate), + issuingCaCertificate: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.issuingCaCertificate), + certificateChain: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.certificateChain), + serialNumber: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.serialNumber) + }) + } + }, + handler: async (req) => { + const { certificate, certificateChain, issuingCaCertificate, serialNumber, ca, commonName } = + await server.services.internalCertificateAuthority.signCertFromCa({ + isInternal: false, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.SIGN_CERT, + metadata: { + caId: ca.id, + dn: ca.dn, + serialNumber + } + } + }); + + await server.services.telemetry.sendPostHogEvents({ + event: PostHogEventTypes.SignCert, + distinctId: getTelemetryDistinctId(req), + organizationId: req.permission.orgId, + properties: { + caId: req.body.caId, + certificateTemplateId: req.body.certificateTemplateId, + commonName, + ...req.auditLogInfo + } + }); + + return { + certificate: certificate.toString("pem"), + certificateChain, + issuingCaCertificate, + serialNumber + }; + } + }); + + server.route({ + method: "POST", + url: "/:serialNumber/revoke", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Revoke", + params: z.object({ + serialNumber: z.string().trim().describe(CERTIFICATES.REVOKE.serialNumber) + }), + body: z.object({ + revocationReason: z.nativeEnum(CrlReason).describe(CERTIFICATES.REVOKE.revocationReason) + }), + response: { + 200: z.object({ + message: z.string().trim(), + serialNumber: z.string().trim().describe(CERTIFICATES.REVOKE.serialNumberRes), + revokedAt: z.date().describe(CERTIFICATES.REVOKE.revokedAt) + }) + } + }, + handler: async (req) => { + const { revokedAt, cert, ca } = await server.services.certificate.revokeCert({ + serialNumber: req.params.serialNumber, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: ca.projectId, + event: { + type: EventType.REVOKE_CERT, + metadata: { + certId: cert.id, + cn: cert.commonName, + serialNumber: cert.serialNumber + } + } + }); + + return { + message: "Successfully revoked certificate", + serialNumber: req.params.serialNumber, + revokedAt + }; + } + }); + + server.route({ + method: "DELETE", + url: "/:serialNumber", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Delete certificate", + params: z.object({ + serialNumber: z.string().trim().describe(CERTIFICATES.DELETE.serialNumber) + }), + response: { + 200: z.object({ + certificate: CertificatesSchema + }) + } + }, + handler: async (req) => { + const { deletedCert } = await server.services.certificate.deleteCert({ + serialNumber: req.params.serialNumber, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: deletedCert.projectId, + event: { + type: EventType.DELETE_CERT, + metadata: { + certId: deletedCert.id, + cn: deletedCert.commonName, + serialNumber: deletedCert.serialNumber + } + } + }); + + return { + certificate: deletedCert + }; + } + }); + + server.route({ + method: "GET", + url: "/:serialNumber/certificate", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificates], + description: "Get certificate body of certificate", + params: z.object({ + serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber) + }), + response: { + 200: z.object({ + certificate: z.string().trim().describe(CERTIFICATES.GET_CERT.certificate), + certificateChain: z.string().trim().nullable().describe(CERTIFICATES.GET_CERT.certificateChain), + serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumberRes) + }) + } + }, + handler: async (req) => { + const { certificate, certificateChain, serialNumber, cert } = await server.services.certificate.getCertBody({ + serialNumber: req.params.serialNumber, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: cert.projectId, + event: { + type: EventType.GET_CERT_BODY, + metadata: { + certId: cert.id, + cn: cert.commonName, + serialNumber: cert.serialNumber + } + } + }); + + return { + certificate, + certificateChain, + serialNumber + }; + } + }); + + server.route({ + method: "POST", + url: "/:serialNumber/pkcs12", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT]), + schema: { + hide: true, + tags: [ApiDocsTags.PkiCertificates], + description: "Download certificate in PKCS12 format", + params: z.object({ + serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber) + }), + body: z.object({ + password: z + .string() + .min(6, "Password must be at least 6 characters long") + .describe("Password for the keystore (minimum 6 characters)"), + alias: z.string().min(1, "Alias is required").describe("Alias for the certificate in the keystore") + }), + response: { + 200: z.any().describe("PKCS12 keystore as binary data") + } + }, + handler: async (req, reply) => { + const { pkcs12Data, cert } = await server.services.certificate.getCertPkcs12({ + serialNumber: req.params.serialNumber, + password: req.body.password, + alias: req.body.alias, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: cert.projectId, + event: { + type: EventType.EXPORT_CERT_PKCS12, + metadata: { + certId: cert.id, + cn: cert.commonName, + serialNumber: cert.serialNumber + } + } + }); + + addNoCacheHeaders(reply); + reply.header("Content-Type", "application/octet-stream"); + reply.header( + "Content-Disposition", + `attachment; filename="certificate-${req.params.serialNumber.replace(new RE2("[^\\w.-]", "g"), "_")}.p12"` + ); + + return pkcs12Data; + } + }); +}; diff --git a/backend/src/server/routes/v1/deprecated-certificate-template-router.ts b/backend/src/server/routes/v1/deprecated-certificate-template-router.ts new file mode 100644 index 000000000..6737b30c0 --- /dev/null +++ b/backend/src/server/routes/v1/deprecated-certificate-template-router.ts @@ -0,0 +1,395 @@ +import { z } from "zod"; + +import { CertificateTemplateEstConfigsSchema } from "@app/db/schemas"; +import { EventType } from "@app/ee/services/audit-log/audit-log-types"; +import { ApiDocsTags, CERTIFICATE_TEMPLATES } from "@app/lib/api-docs"; +import { ms } from "@app/lib/ms"; +import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; +import { slugSchema } from "@app/server/lib/schemas"; +import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { AuthMode } from "@app/services/auth/auth-type"; +import { CertExtendedKeyUsage, CertKeyUsage } from "@app/services/certificate/certificate-types"; +import { sanitizedCertificateTemplate } from "@app/services/certificate-template/certificate-template-schema"; +import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators"; + +const sanitizedEstConfig = CertificateTemplateEstConfigsSchema.pick({ + id: true, + certificateTemplateId: true, + isEnabled: true, + disableBootstrapCertValidation: true +}); + +export const registerDeprecatedCertificateTemplateRouter = async (server: FastifyZodProvider) => { + server.route({ + method: "GET", + url: "/:certificateTemplateId", + config: { + rateLimit: readLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + params: z.object({ + certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.GET.certificateTemplateId) + }), + response: { + 200: sanitizedCertificateTemplate + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const certificateTemplate = await server.services.certificateTemplate.getCertTemplate({ + id: req.params.certificateTemplateId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: certificateTemplate.projectId, + event: { + type: EventType.GET_CERTIFICATE_TEMPLATE, + metadata: { + certificateTemplateId: certificateTemplate.id, + name: certificateTemplate.name + } + } + }); + + return certificateTemplate; + } + }); + + server.route({ + method: "POST", + url: "/", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + body: z.object({ + caId: z.string().describe(CERTIFICATE_TEMPLATES.CREATE.caId), + pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.CREATE.pkiCollectionId), + name: slugSchema().describe(CERTIFICATE_TEMPLATES.CREATE.name), + commonName: validateTemplateRegexField.describe(CERTIFICATE_TEMPLATES.CREATE.commonName), + subjectAlternativeName: validateTemplateRegexField.describe( + CERTIFICATE_TEMPLATES.CREATE.subjectAlternativeName + ), + ttl: z + .string() + .refine((val) => ms(val) > 0, "TTL must be a positive number") + .describe(CERTIFICATE_TEMPLATES.CREATE.ttl), + keyUsages: z + .nativeEnum(CertKeyUsage) + .array() + .optional() + .default([CertKeyUsage.DIGITAL_SIGNATURE, CertKeyUsage.KEY_ENCIPHERMENT]) + .describe(CERTIFICATE_TEMPLATES.CREATE.keyUsages), + extendedKeyUsages: z + .nativeEnum(CertExtendedKeyUsage) + .array() + .optional() + .default([]) + .describe(CERTIFICATE_TEMPLATES.CREATE.extendedKeyUsages) + }), + response: { + 200: sanitizedCertificateTemplate + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const certificateTemplate = await server.services.certificateTemplate.createCertTemplate({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: certificateTemplate.projectId, + event: { + type: EventType.CREATE_CERTIFICATE_TEMPLATE, + metadata: { + certificateTemplateId: certificateTemplate.id, + caId: certificateTemplate.caId, + pkiCollectionId: certificateTemplate.pkiCollectionId as string, + name: certificateTemplate.name, + commonName: certificateTemplate.commonName, + subjectAlternativeName: certificateTemplate.subjectAlternativeName, + ttl: certificateTemplate.ttl, + projectId: certificateTemplate.projectId + } + } + }); + + return certificateTemplate; + } + }); + + server.route({ + method: "PATCH", + url: "/:certificateTemplateId", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + body: z.object({ + caId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.caId), + pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.pkiCollectionId), + name: slugSchema().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.name), + commonName: validateTemplateRegexField.optional().describe(CERTIFICATE_TEMPLATES.UPDATE.commonName), + subjectAlternativeName: validateTemplateRegexField + .optional() + .describe(CERTIFICATE_TEMPLATES.UPDATE.subjectAlternativeName), + ttl: z + .string() + .refine((val) => ms(val) > 0, "TTL must be a positive number") + .optional() + .describe(CERTIFICATE_TEMPLATES.UPDATE.ttl), + keyUsages: z.nativeEnum(CertKeyUsage).array().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.keyUsages), + extendedKeyUsages: z + .nativeEnum(CertExtendedKeyUsage) + .array() + .optional() + .describe(CERTIFICATE_TEMPLATES.UPDATE.extendedKeyUsages) + }), + params: z.object({ + certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.UPDATE.certificateTemplateId) + }), + response: { + 200: sanitizedCertificateTemplate + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const certificateTemplate = await server.services.certificateTemplate.updateCertTemplate({ + ...req.body, + id: req.params.certificateTemplateId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: certificateTemplate.projectId, + event: { + type: EventType.UPDATE_CERTIFICATE_TEMPLATE, + metadata: { + certificateTemplateId: certificateTemplate.id, + name: certificateTemplate.name, + caId: certificateTemplate.caId, + pkiCollectionId: certificateTemplate.pkiCollectionId as string, + commonName: certificateTemplate.commonName, + subjectAlternativeName: certificateTemplate.subjectAlternativeName, + ttl: certificateTemplate.ttl + } + } + }); + + return certificateTemplate; + } + }); + + server.route({ + method: "DELETE", + url: "/:certificateTemplateId", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + params: z.object({ + certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId) + }), + response: { + 200: sanitizedCertificateTemplate + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const certificateTemplate = await server.services.certificateTemplate.deleteCertTemplate({ + id: req.params.certificateTemplateId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: certificateTemplate.projectId, + event: { + type: EventType.DELETE_CERTIFICATE_TEMPLATE, + metadata: { + certificateTemplateId: certificateTemplate.id, + name: certificateTemplate.name + } + } + }); + + return certificateTemplate; + } + }); + + server.route({ + method: "POST", + url: "/:certificateTemplateId/est-config", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + description: "Create Certificate Template EST configuration", + params: z.object({ + certificateTemplateId: z.string().trim() + }), + body: z + .object({ + caChain: z.string().trim().optional(), + passphrase: z.string().min(1), + isEnabled: z.boolean().default(true), + disableBootstrapCertValidation: z.boolean().default(false) + }) + .refine( + ({ caChain, disableBootstrapCertValidation }) => + disableBootstrapCertValidation || (!disableBootstrapCertValidation && caChain), + "CA chain is required" + ), + response: { + 200: sanitizedEstConfig + } + }, + handler: async (req) => { + const estConfig = await server.services.certificateTemplate.createEstConfiguration({ + certificateTemplateId: req.params.certificateTemplateId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: estConfig.projectId, + event: { + type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG, + metadata: { + certificateTemplateId: estConfig.certificateTemplateId, + isEnabled: estConfig.isEnabled as boolean + } + } + }); + + return estConfig; + } + }); + + server.route({ + method: "PATCH", + url: "/:certificateTemplateId/est-config", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + description: "Update Certificate Template EST configuration", + params: z.object({ + certificateTemplateId: z.string().trim() + }), + body: z.object({ + caChain: z.string().trim().optional(), + passphrase: z.string().min(1).optional(), + disableBootstrapCertValidation: z.boolean().optional(), + isEnabled: z.boolean().optional() + }), + response: { + 200: sanitizedEstConfig + } + }, + handler: async (req) => { + const estConfig = await server.services.certificateTemplate.updateEstConfiguration({ + certificateTemplateId: req.params.certificateTemplateId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: estConfig.projectId, + event: { + type: EventType.UPDATE_CERTIFICATE_TEMPLATE_EST_CONFIG, + metadata: { + certificateTemplateId: estConfig.certificateTemplateId, + isEnabled: estConfig.isEnabled as boolean + } + } + }); + + return estConfig; + } + }); + + server.route({ + method: "GET", + url: "/:certificateTemplateId/est-config", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateTemplates], + description: "Get Certificate Template EST configuration", + params: z.object({ + certificateTemplateId: z.string().trim() + }), + response: { + 200: sanitizedEstConfig.extend({ + caChain: z.string() + }) + } + }, + handler: async (req) => { + const estConfig = await server.services.certificateTemplate.getEstConfiguration({ + isInternal: false, + certificateTemplateId: req.params.certificateTemplateId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: estConfig.projectId, + event: { + type: EventType.GET_CERTIFICATE_TEMPLATE_EST_CONFIG, + metadata: { + certificateTemplateId: estConfig.certificateTemplateId + } + } + }); + + return estConfig; + } + }); +}; diff --git a/backend/src/server/routes/v1/deprecated-pki-alert-router.ts b/backend/src/server/routes/v1/deprecated-pki-alert-router.ts new file mode 100644 index 000000000..bfabc5a89 --- /dev/null +++ b/backend/src/server/routes/v1/deprecated-pki-alert-router.ts @@ -0,0 +1,205 @@ +import { z } from "zod"; + +import { PkiAlertsSchema } from "@app/db/schemas"; +import { EventType } from "@app/ee/services/audit-log/audit-log-types"; +import { ALERTS, ApiDocsTags } from "@app/lib/api-docs"; +import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; +import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { AuthMode } from "@app/services/auth/auth-type"; +import { PkiAlertEventType } from "@app/services/pki-alert-v2/pki-alert-v2-types"; + +export const registerDeprecatedPkiAlertRouter = async (server: FastifyZodProvider) => { + server.route({ + method: "POST", + url: "/", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + tags: [ApiDocsTags.PkiAlerting], + description: "Create PKI alert", + body: z.object({ + projectId: z.string().trim().describe(ALERTS.CREATE.projectId), + pkiCollectionId: z.string().trim().describe(ALERTS.CREATE.pkiCollectionId), + name: z.string().trim().describe(ALERTS.CREATE.name), + alertBeforeDays: z.number().describe(ALERTS.CREATE.alertBeforeDays), + emails: z + .array(z.string().trim().email({ message: "Invalid email address" })) + .min(1, { message: "You must specify at least 1 email" }) + .max(5, { message: "You can specify a maximum of 5 emails" }) + .describe(ALERTS.CREATE.emails) + }), + response: { + 200: PkiAlertsSchema + } + }, + handler: async (req) => { + const alert = await server.services.pkiAlert.createPkiAlert({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: alert.projectId, + event: { + type: EventType.CREATE_PKI_ALERT, + metadata: { + pkiAlertId: alert.id, + pkiCollectionId: alert.pkiCollectionId, + name: alert.name, + alertBefore: alert.alertBeforeDays.toString(), + eventType: PkiAlertEventType.EXPIRATION, + recipientEmails: alert.recipientEmails + } + } + }); + + return alert; + } + }); + + server.route({ + method: "GET", + url: "/:alertId", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + tags: [ApiDocsTags.PkiAlerting], + description: "Get PKI alert", + params: z.object({ + alertId: z.string().trim().describe(ALERTS.GET.alertId) + }), + response: { + 200: PkiAlertsSchema + } + }, + handler: async (req) => { + const alert = await server.services.pkiAlert.getPkiAlertById({ + alertId: req.params.alertId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: alert.projectId, + event: { + type: EventType.GET_PKI_ALERT, + metadata: { + pkiAlertId: alert.id + } + } + }); + + return alert; + } + }); + + server.route({ + method: "PATCH", + url: "/:alertId", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + tags: [ApiDocsTags.PkiAlerting], + description: "Update PKI alert", + params: z.object({ + alertId: z.string().trim().describe(ALERTS.UPDATE.alertId) + }), + body: z.object({ + name: z.string().trim().optional().describe(ALERTS.UPDATE.name), + alertBeforeDays: z.number().optional().describe(ALERTS.UPDATE.alertBeforeDays), + pkiCollectionId: z.string().trim().optional().describe(ALERTS.UPDATE.pkiCollectionId), + emails: z + .array(z.string().trim().email({ message: "Invalid email address" })) + .min(1, { message: "You must specify at least 1 email" }) + .max(5, { message: "You can specify a maximum of 5 emails" }) + .optional() + .describe(ALERTS.UPDATE.emails) + }), + response: { + 200: PkiAlertsSchema + } + }, + handler: async (req) => { + const alert = await server.services.pkiAlert.updatePkiAlert({ + alertId: req.params.alertId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: alert.projectId, + event: { + type: EventType.UPDATE_PKI_ALERT, + metadata: { + pkiAlertId: alert.id, + pkiCollectionId: alert.pkiCollectionId, + name: alert.name, + alertBefore: alert.alertBeforeDays.toString(), + eventType: PkiAlertEventType.EXPIRATION, + recipientEmails: alert.recipientEmails + } + } + }); + + return alert; + } + }); + + server.route({ + method: "DELETE", + url: "/:alertId", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + tags: [ApiDocsTags.PkiAlerting], + description: "Delete PKI alert", + params: z.object({ + alertId: z.string().trim().describe(ALERTS.DELETE.alertId) + }), + response: { + 200: PkiAlertsSchema + } + }, + handler: async (req) => { + const alert = await server.services.pkiAlert.deletePkiAlert({ + alertId: req.params.alertId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: alert.projectId, + event: { + type: EventType.DELETE_PKI_ALERT, + metadata: { + pkiAlertId: alert.id + } + } + }); + + return alert; + } + }); +}; diff --git a/backend/src/server/routes/v1/index.ts b/backend/src/server/routes/v1/index.ts index b480a5144..fc509a5ab 100644 --- a/backend/src/server/routes/v1/index.ts +++ b/backend/src/server/routes/v1/index.ts @@ -11,10 +11,14 @@ import { registerAuthRoutes } from "./auth-router"; import { registerProjectBotRouter } from "./bot-router"; import { registerCaRouter } from "./certificate-authority-router"; import { CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP } from "./certificate-authority-routers"; +import { registerGeneralCertificateAuthorityRouter } from "./certificate-authority-routers/general-certificate-authority-router"; import { registerCertificateProfilesRouter } from "./certificate-profiles-router"; -import { registerCertRouter } from "./certificate-router"; +import { registerCertificateRouter } from "./certificate-router"; import { registerCertificateTemplateRouter } from "./certificate-template-router"; +import { registerDeprecatedCertRouter } from "./deprecated-certificate-router"; +import { registerDeprecatedCertificateTemplateRouter } from "./deprecated-certificate-template-router"; import { registerDeprecatedIdentityProjectMembershipRouter } from "./deprecated-identity-project-membership-router"; +import { registerDeprecatedPkiAlertRouter } from "./deprecated-pki-alert-router"; import { registerDeprecatedProjectEnvRouter } from "./deprecated-project-env-router"; import { registerDeprecatedProjectMembershipRouter } from "./deprecated-project-membership-router"; import { registerDeprecatedProjectRouter } from "./deprecated-project-router"; @@ -148,6 +152,39 @@ export const registerV1Routes = async (server: FastifyZodProvider) => { prefix: "/projects/:projectId/memberships" }); + await server.register( + async (pkiRouter) => { + await pkiRouter.register( + async (caRouter) => { + for await (const [caType, router] of Object.entries(CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP)) { + await caRouter.register(router, { prefix: `/${caType}` }); + } + + await caRouter.register(registerGeneralCertificateAuthorityRouter); + }, + { + prefix: "/ca" + } + ); + await pkiRouter.register(registerCertificateRouter, { prefix: "/certificates" }); + await pkiRouter.register(registerCertificateTemplateRouter, { prefix: "/certificate-templates" }); + await pkiRouter.register(registerCertificateProfilesRouter, { prefix: "/certificate-profiles" }); + await pkiRouter.register(registerPkiAlertRouter, { prefix: "/alerts" }); + await pkiRouter.register( + async (pkiSyncRouter) => { + await pkiSyncRouter.register(registerPkiSyncRouter); + for await (const [destination, router] of Object.entries(PKI_SYNC_REGISTER_ROUTER_MAP)) { + await pkiSyncRouter.register(router, { prefix: `/${destination}` }); + } + }, + { prefix: "/syncs" } + ); + }, + { prefix: "/cert-manager" } + ); + + // NOTE: THESE /pki/* ENDPOINTS ARE TO BE DEPRECATED IN FAVOR OF /cert-manager/* + // DO NOT EXTEND THEM ANYMORE!!! await server.register( async (pkiRouter) => { await pkiRouter.register(registerCaRouter, { prefix: "/ca" }); @@ -161,10 +198,10 @@ export const registerV1Routes = async (server: FastifyZodProvider) => { prefix: "/ca" } ); - await pkiRouter.register(registerCertRouter, { prefix: "/certificates" }); - await pkiRouter.register(registerCertificateTemplateRouter, { prefix: "/certificate-templates" }); + await pkiRouter.register(registerDeprecatedCertRouter, { prefix: "/certificates" }); + await pkiRouter.register(registerDeprecatedCertificateTemplateRouter, { prefix: "/certificate-templates" }); await pkiRouter.register(registerCertificateProfilesRouter, { prefix: "/certificate-profiles" }); - await pkiRouter.register(registerPkiAlertRouter, { prefix: "/alerts" }); + await pkiRouter.register(registerDeprecatedPkiAlertRouter, { prefix: "/alerts" }); await pkiRouter.register(registerPkiCollectionRouter, { prefix: "/collections" }); await pkiRouter.register(registerPkiSubscriberRouter, { prefix: "/subscribers" }); await pkiRouter.register( diff --git a/backend/src/server/routes/v1/pki-alert-router.ts b/backend/src/server/routes/v1/pki-alert-router.ts index 60a906c3a..459b5cc6c 100644 --- a/backend/src/server/routes/v1/pki-alert-router.ts +++ b/backend/src/server/routes/v1/pki-alert-router.ts @@ -1,12 +1,18 @@ import { z } from "zod"; -import { PkiAlertsSchema } from "@app/db/schemas"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; -import { ALERTS, ApiDocsTags } from "@app/lib/api-docs"; +import { ApiDocsTags } from "@app/lib/api-docs"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; -import { PkiAlertEventType } from "@app/services/pki-alert-v2/pki-alert-v2-types"; +import { + CreatePkiAlertV2Schema, + createSecureAlertBeforeValidator, + PkiAlertChannelType, + PkiAlertEventType, + PkiFilterRuleSchema, + UpdatePkiAlertV2Schema +} from "@app/services/pki-alert-v2/pki-alert-v2-types"; export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { server.route({ @@ -17,25 +23,40 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + description: "Create a new PKI alert", tags: [ApiDocsTags.PkiAlerting], - description: "Create PKI alert", - body: z.object({ - projectId: z.string().trim().describe(ALERTS.CREATE.projectId), - pkiCollectionId: z.string().trim().describe(ALERTS.CREATE.pkiCollectionId), - name: z.string().trim().describe(ALERTS.CREATE.name), - alertBeforeDays: z.number().describe(ALERTS.CREATE.alertBeforeDays), - emails: z - .array(z.string().trim().email({ message: "Invalid email address" })) - .min(1, { message: "You must specify at least 1 email" }) - .max(5, { message: "You can specify a maximum of 5 emails" }) - .describe(ALERTS.CREATE.emails) + body: CreatePkiAlertV2Schema.extend({ + projectId: z.string().uuid().describe("Project ID") }), response: { - 200: PkiAlertsSchema + 200: z.object({ + alert: z.object({ + id: z.string().uuid(), + name: z.string(), + description: z.string().nullable(), + eventType: z.nativeEnum(PkiAlertEventType), + alertBefore: z.string(), + filters: z.array(PkiFilterRuleSchema), + enabled: z.boolean(), + projectId: z.string().uuid(), + channels: z.array( + z.object({ + id: z.string().uuid(), + channelType: z.nativeEnum(PkiAlertChannelType), + config: z.record(z.any()), + enabled: z.boolean(), + createdAt: z.date(), + updatedAt: z.date() + }) + ), + createdAt: z.date(), + updatedAt: z.date() + }) + }) } }, handler: async (req) => { - const alert = await server.services.pkiAlert.createPkiAlert({ + const alert = await server.services.pkiAlertV2.createAlert({ actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -45,21 +66,79 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - projectId: alert.projectId, + projectId: req.body.projectId, event: { type: EventType.CREATE_PKI_ALERT, metadata: { pkiAlertId: alert.id, - pkiCollectionId: alert.pkiCollectionId, name: alert.name, - alertBefore: alert.alertBeforeDays.toString(), - eventType: PkiAlertEventType.EXPIRATION, - recipientEmails: alert.recipientEmails + eventType: alert.eventType, + alertBefore: alert.alertBefore } } }); - return alert; + return { alert }; + } + }); + + server.route({ + method: "GET", + url: "/", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + description: "List PKI alerts for a project", + tags: [ApiDocsTags.PkiAlerting], + querystring: z.object({ + projectId: z.string().uuid(), + search: z.string().optional(), + eventType: z.nativeEnum(PkiAlertEventType).optional(), + enabled: z.coerce.boolean().optional(), + limit: z.coerce.number().min(1).max(100).default(20), + offset: z.coerce.number().min(0).default(0) + }), + response: { + 200: z.object({ + alerts: z.array( + z.object({ + id: z.string().uuid(), + name: z.string(), + description: z.string().nullable(), + eventType: z.nativeEnum(PkiAlertEventType), + alertBefore: z.string(), + filters: z.array(PkiFilterRuleSchema), + enabled: z.boolean(), + channels: z.array( + z.object({ + id: z.string().uuid(), + channelType: z.nativeEnum(PkiAlertChannelType), + config: z.record(z.any()), + enabled: z.boolean(), + createdAt: z.date(), + updatedAt: z.date() + }) + ), + createdAt: z.date(), + updatedAt: z.date() + }) + ), + total: z.number() + }) + } + }, + handler: async (req) => { + const alerts = await server.services.pkiAlertV2.listAlerts({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.query + }); + + return alerts; } }); @@ -71,17 +150,40 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + description: "Get a PKI alert by ID", tags: [ApiDocsTags.PkiAlerting], - description: "Get PKI alert", params: z.object({ - alertId: z.string().trim().describe(ALERTS.GET.alertId) + alertId: z.string().uuid().describe("Alert ID") }), response: { - 200: PkiAlertsSchema + 200: z.object({ + alert: z.object({ + id: z.string().uuid(), + name: z.string(), + description: z.string().nullable(), + eventType: z.nativeEnum(PkiAlertEventType), + alertBefore: z.string(), + filters: z.array(PkiFilterRuleSchema), + enabled: z.boolean(), + projectId: z.string().uuid(), + channels: z.array( + z.object({ + id: z.string().uuid(), + channelType: z.nativeEnum(PkiAlertChannelType), + config: z.record(z.any()), + enabled: z.boolean(), + createdAt: z.date(), + updatedAt: z.date() + }) + ), + createdAt: z.date(), + updatedAt: z.date() + }) + }) } }, handler: async (req) => { - const alert = await server.services.pkiAlert.getPkiAlertById({ + const alert = await server.services.pkiAlertV2.getAlertById({ alertId: req.params.alertId, actor: req.permission.type, actorId: req.permission.id, @@ -100,7 +202,7 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { } }); - return alert; + return { alert }; } }); @@ -108,32 +210,45 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { method: "PATCH", url: "/:alertId", config: { - rateLimit: readLimit + rateLimit: writeLimit }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + description: "Update a PKI alert", tags: [ApiDocsTags.PkiAlerting], - description: "Update PKI alert", params: z.object({ - alertId: z.string().trim().describe(ALERTS.UPDATE.alertId) - }), - body: z.object({ - name: z.string().trim().optional().describe(ALERTS.UPDATE.name), - alertBeforeDays: z.number().optional().describe(ALERTS.UPDATE.alertBeforeDays), - pkiCollectionId: z.string().trim().optional().describe(ALERTS.UPDATE.pkiCollectionId), - emails: z - .array(z.string().trim().email({ message: "Invalid email address" })) - .min(1, { message: "You must specify at least 1 email" }) - .max(5, { message: "You can specify a maximum of 5 emails" }) - .optional() - .describe(ALERTS.UPDATE.emails) + alertId: z.string().uuid().describe("Alert ID") }), + body: UpdatePkiAlertV2Schema, response: { - 200: PkiAlertsSchema + 200: z.object({ + alert: z.object({ + id: z.string().uuid(), + name: z.string(), + description: z.string().nullable(), + eventType: z.nativeEnum(PkiAlertEventType), + alertBefore: z.string(), + filters: z.array(PkiFilterRuleSchema), + enabled: z.boolean(), + projectId: z.string().uuid(), + channels: z.array( + z.object({ + id: z.string().uuid(), + channelType: z.nativeEnum(PkiAlertChannelType), + config: z.record(z.any()), + enabled: z.boolean(), + createdAt: z.date(), + updatedAt: z.date() + }) + ), + createdAt: z.date(), + updatedAt: z.date() + }) + }) } }, handler: async (req) => { - const alert = await server.services.pkiAlert.updatePkiAlert({ + const alert = await server.services.pkiAlertV2.updateAlert({ alertId: req.params.alertId, actor: req.permission.type, actorId: req.permission.id, @@ -149,16 +264,14 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { type: EventType.UPDATE_PKI_ALERT, metadata: { pkiAlertId: alert.id, - pkiCollectionId: alert.pkiCollectionId, name: alert.name, - alertBefore: alert.alertBeforeDays.toString(), - eventType: PkiAlertEventType.EXPIRATION, - recipientEmails: alert.recipientEmails + eventType: alert.eventType, + alertBefore: alert.alertBefore } } }); - return alert; + return { alert }; } }); @@ -170,17 +283,40 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + description: "Delete a PKI alert", tags: [ApiDocsTags.PkiAlerting], - description: "Delete PKI alert", params: z.object({ - alertId: z.string().trim().describe(ALERTS.DELETE.alertId) + alertId: z.string().uuid().describe("Alert ID") }), response: { - 200: PkiAlertsSchema + 200: z.object({ + alert: z.object({ + id: z.string().uuid(), + name: z.string(), + description: z.string().nullable(), + eventType: z.nativeEnum(PkiAlertEventType), + alertBefore: z.string(), + filters: z.array(PkiFilterRuleSchema), + enabled: z.boolean(), + projectId: z.string().uuid(), + channels: z.array( + z.object({ + id: z.string().uuid(), + channelType: z.nativeEnum(PkiAlertChannelType), + config: z.record(z.any()), + enabled: z.boolean(), + createdAt: z.date(), + updatedAt: z.date() + }) + ), + createdAt: z.date(), + updatedAt: z.date() + }) + }) } }, handler: async (req) => { - const alert = await server.services.pkiAlert.deletePkiAlert({ + const alert = await server.services.pkiAlertV2.deleteAlert({ alertId: req.params.alertId, actor: req.permission.type, actorId: req.permission.id, @@ -199,7 +335,109 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { } }); - return alert; + return { alert }; + } + }); + + server.route({ + method: "GET", + url: "/:alertId/certificates", + config: { + rateLimit: readLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + description: "List certificates that match an alert's filter rules", + tags: [ApiDocsTags.PkiAlerting], + params: z.object({ + alertId: z.string().uuid().describe("Alert ID") + }), + querystring: z.object({ + limit: z.coerce.number().min(1).max(100).default(20), + offset: z.coerce.number().min(0).default(0) + }), + response: { + 200: z.object({ + certificates: z.array( + z.object({ + id: z.string().uuid(), + serialNumber: z.string(), + commonName: z.string(), + san: z.array(z.string()), + profileName: z.string().nullable(), + enrollmentType: z.string().nullable(), + notBefore: z.date(), + notAfter: z.date(), + status: z.string() + }) + ), + total: z.number() + }) + } + }, + handler: async (req) => { + const result = await server.services.pkiAlertV2.listMatchingCertificates({ + alertId: req.params.alertId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.query + }); + + return result; + } + }); + + server.route({ + method: "POST", + url: "/preview/certificates", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + description: "Preview certificates that would match the given filter rules", + tags: [ApiDocsTags.PkiAlerting], + body: z.object({ + projectId: z.string().uuid().describe("Project ID"), + filters: z.array(PkiFilterRuleSchema), + alertBefore: z + .string() + .refine(createSecureAlertBeforeValidator(), "Must be in format like '30d', '1w', '3m', '1y'") + .describe("Alert timing (e.g., '30d', '1w')"), + limit: z.coerce.number().min(1).max(100).default(20), + offset: z.coerce.number().min(0).default(0) + }), + response: { + 200: z.object({ + certificates: z.array( + z.object({ + id: z.string().uuid(), + serialNumber: z.string(), + commonName: z.string(), + san: z.array(z.string()), + profileName: z.string().nullable(), + enrollmentType: z.string().nullable(), + notBefore: z.date(), + notAfter: z.date(), + status: z.string() + }) + ), + total: z.number() + }) + } + }, + handler: async (req) => { + const result = await server.services.pkiAlertV2.listCurrentMatchingCertificates({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + ...req.body + }); + + return result; } }); }; diff --git a/backend/src/server/routes/v2/certificate-templates-v2-router.ts b/backend/src/server/routes/v2/deprecated-certificate-templates-v2-router.ts similarity index 100% rename from backend/src/server/routes/v2/certificate-templates-v2-router.ts rename to backend/src/server/routes/v2/deprecated-certificate-templates-v2-router.ts diff --git a/backend/src/server/routes/v2/index.ts b/backend/src/server/routes/v2/index.ts index d3d91a3ba..7a747a697 100644 --- a/backend/src/server/routes/v2/index.ts +++ b/backend/src/server/routes/v2/index.ts @@ -1,5 +1,5 @@ import { registerCaRouter } from "./certificate-authority-router"; -import { registerCertificateTemplatesV2Router } from "./certificate-templates-v2-router"; +import { registerCertificateTemplatesV2Router } from "./deprecated-certificate-templates-v2-router"; import { registerDeprecatedGroupProjectRouter } from "./deprecated-group-project-router"; import { registerDeprecatedIdentityProjectRouter } from "./deprecated-identity-project-router"; import { registerDeprecatedProjectMembershipRouter } from "./deprecated-project-membership-router"; diff --git a/backend/src/server/routes/v3/certificates-router.ts b/backend/src/server/routes/v3/deprecated-certificates-router.ts similarity index 100% rename from backend/src/server/routes/v3/certificates-router.ts rename to backend/src/server/routes/v3/deprecated-certificates-router.ts diff --git a/backend/src/server/routes/v3/index.ts b/backend/src/server/routes/v3/index.ts index 4ee4566c1..c770d0890 100644 --- a/backend/src/server/routes/v3/index.ts +++ b/backend/src/server/routes/v3/index.ts @@ -1,4 +1,4 @@ -import { registerCertificatesRouter } from "./certificates-router"; +import { registerCertificatesRouter } from "./deprecated-certificates-router"; import { registerDeprecatedSecretRouter } from "./deprecated-secret-router"; import { registerExternalMigrationRouter } from "./external-migration-router"; import { registerLoginRouter } from "./login-router"; diff --git a/backend/src/services/certificate-authority/acme/acme-certificate-authority-fns.ts b/backend/src/services/certificate-authority/acme/acme-certificate-authority-fns.ts index ff95083c6..f25feb1ab 100644 --- a/backend/src/services/certificate-authority/acme/acme-certificate-authority-fns.ts +++ b/backend/src/services/certificate-authority/acme/acme-certificate-authority-fns.ts @@ -377,7 +377,6 @@ export const AcmeCertificateAuthorityFns = ({ name, projectId, configuration, - enableDirectIssuance, actor, status }: { @@ -385,7 +384,6 @@ export const AcmeCertificateAuthorityFns = ({ name: string; projectId: string; configuration: TCreateAcmeCertificateAuthorityDTO["configuration"]; - enableDirectIssuance: boolean; actor: OrgServiceActor; }) => { if (crypto.isFipsModeEnabled()) { @@ -425,7 +423,7 @@ export const AcmeCertificateAuthorityFns = ({ const ca = await certificateAuthorityDAL.create( { projectId, - enableDirectIssuance, + enableDirectIssuance: false, name, status }, @@ -473,14 +471,12 @@ export const AcmeCertificateAuthorityFns = ({ id, status, configuration, - enableDirectIssuance, actor, name }: { id: string; status?: CaStatus; configuration: TUpdateAcmeCertificateAuthorityDTO["configuration"]; - enableDirectIssuance?: boolean; actor: OrgServiceActor; name?: string; }) => { @@ -541,13 +537,12 @@ export const AcmeCertificateAuthorityFns = ({ ); } - if (name || status || enableDirectIssuance) { + if (name || status) { await certificateAuthorityDAL.updateById( id, { name, - status, - enableDirectIssuance + status }, tx ); diff --git a/backend/src/services/certificate-authority/azure-ad-cs/azure-ad-cs-certificate-authority-fns.ts b/backend/src/services/certificate-authority/azure-ad-cs/azure-ad-cs-certificate-authority-fns.ts index 26f59a402..d1d791a90 100644 --- a/backend/src/services/certificate-authority/azure-ad-cs/azure-ad-cs-certificate-authority-fns.ts +++ b/backend/src/services/certificate-authority/azure-ad-cs/azure-ad-cs-certificate-authority-fns.ts @@ -597,7 +597,6 @@ export const AzureAdCsCertificateAuthorityFns = ({ name, projectId, configuration, - enableDirectIssuance, actor, status }: { @@ -605,16 +604,8 @@ export const AzureAdCsCertificateAuthorityFns = ({ name: string; projectId: string; configuration: TCreateAzureAdCsCertificateAuthorityDTO["configuration"]; - enableDirectIssuance: boolean; actor: OrgServiceActor; }) => { - // Azure ADCS does not support direct issuance - enforce this restriction - if (enableDirectIssuance) { - throw new BadRequestError({ - message: "Azure ADCS Certificate Authorities do not support direct issuance" - }); - } - const { azureAdcsConnectionId } = configuration; const appConnection = await appConnectionDAL.findById(azureAdcsConnectionId); @@ -679,24 +670,15 @@ export const AzureAdCsCertificateAuthorityFns = ({ id, status, configuration, - enableDirectIssuance, actor, name }: { id: string; status?: CaStatus; configuration: TUpdateAzureAdCsCertificateAuthorityDTO["configuration"]; - enableDirectIssuance?: boolean; actor: OrgServiceActor; name?: string; }) => { - // Azure ADCS does not support direct issuance - enforce this restriction - if (enableDirectIssuance) { - throw new BadRequestError({ - message: "Azure ADCS Certificate Authorities do not support direct issuance" - }); - } - const updatedCa = await certificateAuthorityDAL.transaction(async (tx) => { if (configuration) { const { azureAdcsConnectionId } = configuration; @@ -737,13 +719,12 @@ export const AzureAdCsCertificateAuthorityFns = ({ ); } - if (name || status || enableDirectIssuance !== undefined) { + if (name || status) { await certificateAuthorityDAL.updateById( id, { name, - status, - enableDirectIssuance: false // Always false for Azure ADCS CAs + status }, tx ); diff --git a/backend/src/services/certificate-authority/certificate-authority-schemas.ts b/backend/src/services/certificate-authority/certificate-authority-schemas.ts index 5ecc50a4b..b50fb6293 100644 --- a/backend/src/services/certificate-authority/certificate-authority-schemas.ts +++ b/backend/src/services/certificate-authority/certificate-authority-schemas.ts @@ -19,14 +19,10 @@ export const GenericCreateCertificateAuthorityFieldsSchema = (type: CaType) => z.object({ name: slugSchema({ field: "name" }).describe(CertificateAuthorities.CREATE(type).name), projectId: z.string().uuid("Project ID must be valid").describe(CertificateAuthorities.CREATE(type).projectId), - enableDirectIssuance: z.boolean().describe(CertificateAuthorities.CREATE(type).enableDirectIssuance), status: z.nativeEnum(CaStatus).describe(CertificateAuthorities.CREATE(type).status) }); export const GenericUpdateCertificateAuthorityFieldsSchema = (type: CaType) => z.object({ - name: slugSchema({ field: "name" }).optional().describe(CertificateAuthorities.UPDATE(type).name), - projectId: z.string().uuid("Project ID must be valid").describe(CertificateAuthorities.UPDATE(type).projectId), - enableDirectIssuance: z.boolean().optional().describe(CertificateAuthorities.UPDATE(type).enableDirectIssuance), status: z.nativeEnum(CaStatus).optional().describe(CertificateAuthorities.UPDATE(type).status) }); diff --git a/backend/src/services/certificate-authority/certificate-authority-service.ts b/backend/src/services/certificate-authority/certificate-authority-service.ts index ed27f7571..715400b5f 100644 --- a/backend/src/services/certificate-authority/certificate-authority-service.ts +++ b/backend/src/services/certificate-authority/certificate-authority-service.ts @@ -123,7 +123,7 @@ export const certificateAuthorityServiceFactory = ({ }); const createCertificateAuthority = async ( - { type, projectId, name, enableDirectIssuance, configuration, status }: TCreateCertificateAuthorityDTO, + { type, projectId, name, configuration, status }: TCreateCertificateAuthorityDTO, actor: OrgServiceActor ) => { const { permission } = await permissionService.getProjectPermission({ @@ -145,7 +145,6 @@ export const certificateAuthorityServiceFactory = ({ ...(configuration as TCreateInternalCertificateAuthorityDTO["configuration"]), isInternal: true, projectId, - enableDirectIssuance, name }); @@ -171,7 +170,6 @@ export const certificateAuthorityServiceFactory = ({ name, projectId, configuration: configuration as TCreateAcmeCertificateAuthorityDTO["configuration"], - enableDirectIssuance, status, actor }); @@ -182,7 +180,6 @@ export const certificateAuthorityServiceFactory = ({ name, projectId, configuration: configuration as TCreateAzureAdCsCertificateAuthorityDTO["configuration"], - enableDirectIssuance, status, actor }); @@ -191,18 +188,12 @@ export const certificateAuthorityServiceFactory = ({ throw new BadRequestError({ message: "Invalid certificate authority type" }); }; - const findCertificateAuthorityByNameAndProjectId = async ( - { caName, type, projectId }: { caName: string; type: CaType; projectId: string }, - actor: OrgServiceActor - ) => { - const certificateAuthority = await certificateAuthorityDAL.findByNameAndProjectIdWithAssociatedCa( - caName, - projectId - ); + const findCertificateAuthorityById = async ({ id, type }: { id: string; type: CaType }, actor: OrgServiceActor) => { + const certificateAuthority = await certificateAuthorityDAL.findByIdWithAssociatedCa(id); if (!certificateAuthority) throw new NotFoundError({ - message: `Could not find certificate authority with name "${caName}" in project "${projectId}"` + message: `Could not find certificate authority with id "${id}"` }); const { permission } = await permissionService.getProjectPermission({ @@ -222,7 +213,7 @@ export const certificateAuthorityServiceFactory = ({ if (type === CaType.INTERNAL) { if (!certificateAuthority.internalCa?.id) { throw new NotFoundError({ - message: `Internal certificate authority with name "${caName}" in project "${projectId}" not found` + message: `Internal certificate authority with id "${id}" not found` }); } @@ -239,7 +230,7 @@ export const certificateAuthorityServiceFactory = ({ if (certificateAuthority.externalCa?.type !== type) { throw new NotFoundError({ - message: `Could not find external certificate authority with name "${caName}" in project "${projectId}" and type "${type}"` + message: `Could not find external certificate authority with id ${id} and type "${type}"` }); } @@ -303,17 +294,14 @@ export const certificateAuthorityServiceFactory = ({ }; const updateCertificateAuthority = async ( - { caName, type, configuration, enableDirectIssuance, status, name, projectId }: TUpdateCertificateAuthorityDTO, + { id, type, configuration, status, name }: TUpdateCertificateAuthorityDTO, actor: OrgServiceActor ) => { - const certificateAuthority = await certificateAuthorityDAL.findByNameAndProjectIdWithAssociatedCa( - caName, - projectId - ); + const certificateAuthority = await certificateAuthorityDAL.findByIdWithAssociatedCa(id); if (!certificateAuthority) throw new NotFoundError({ - message: `Could not find certificate authority with name "${caName}" in project "${projectId}"` + message: `Could not find certificate authority with id "${id}"` }); const { permission } = await permissionService.getProjectPermission({ @@ -333,13 +321,12 @@ export const certificateAuthorityServiceFactory = ({ if (type === CaType.INTERNAL) { if (!certificateAuthority.internalCa?.id) { throw new NotFoundError({ - message: `Internal certificate authority with name "${caName}" in project "${projectId}" not found` + message: `Internal certificate authority with id "${id}" not found` }); } const updatedCa = await internalCertificateAuthorityService.updateCaById({ isInternal: true, - enableDirectIssuance, caId: certificateAuthority.id, status, name @@ -366,7 +353,6 @@ export const certificateAuthorityServiceFactory = ({ return acmeFns.updateCertificateAuthority({ id: certificateAuthority.id, configuration: configuration as TUpdateAcmeCertificateAuthorityDTO["configuration"], - enableDirectIssuance, actor, status, name @@ -377,7 +363,6 @@ export const certificateAuthorityServiceFactory = ({ return azureAdCsFns.updateCertificateAuthority({ id: certificateAuthority.id, configuration: configuration as TUpdateAzureAdCsCertificateAuthorityDTO["configuration"], - enableDirectIssuance, actor, status, name @@ -387,18 +372,12 @@ export const certificateAuthorityServiceFactory = ({ throw new BadRequestError({ message: "Invalid certificate authority type" }); }; - const deleteCertificateAuthority = async ( - { caName, type, projectId }: { caName: string; type: CaType; projectId: string }, - actor: OrgServiceActor - ) => { - const certificateAuthority = await certificateAuthorityDAL.findByNameAndProjectIdWithAssociatedCa( - caName, - projectId - ); + const deleteCertificateAuthority = async ({ id, type }: { id: string; type: CaType }, actor: OrgServiceActor) => { + const certificateAuthority = await certificateAuthorityDAL.findByIdWithAssociatedCa(id); if (!certificateAuthority) throw new NotFoundError({ - message: `Could not find certificate authority with name "${caName}" in project "${projectId}"` + message: `Could not find certificate authority with id "${id}"` }); const { permission } = await permissionService.getProjectPermission({ @@ -489,7 +468,7 @@ export const certificateAuthorityServiceFactory = ({ return { createCertificateAuthority, - findCertificateAuthorityByNameAndProjectId, + findCertificateAuthorityById, listCertificateAuthoritiesByProjectId, updateCertificateAuthority, deleteCertificateAuthority, diff --git a/backend/src/services/certificate-authority/certificate-authority-types.ts b/backend/src/services/certificate-authority/certificate-authority-types.ts index 13b5cec40..4f1a67c0e 100644 --- a/backend/src/services/certificate-authority/certificate-authority-types.ts +++ b/backend/src/services/certificate-authority/certificate-authority-types.ts @@ -19,10 +19,9 @@ export type TCertificateAuthorityInput = | TAcmeCertificateAuthorityInput | TCreateAzureAdCsCertificateAuthorityDTO; -export type TCreateCertificateAuthorityDTO = Omit; +export type TCreateCertificateAuthorityDTO = Omit; export type TUpdateCertificateAuthorityDTO = Partial> & { type: CaType; - caName: string; - projectId: string; + id: string; }; diff --git a/backend/src/services/certificate-authority/internal/internal-certificate-authority-fns.ts b/backend/src/services/certificate-authority/internal/internal-certificate-authority-fns.ts index 6f730fd72..2c5cb4b97 100644 --- a/backend/src/services/certificate-authority/internal/internal-certificate-authority-fns.ts +++ b/backend/src/services/certificate-authority/internal/internal-certificate-authority-fns.ts @@ -136,8 +136,8 @@ export const InternalCertificateAuthorityFns = ({ const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id }); const appCfg = getConfig(); - const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`; - const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`; + const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/crl/${caCrl.id}/der`; + const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/ca/internal/${ca.id}/certificates/${caCert.id}/der`; const extensions: x509.Extension[] = [ new x509.BasicConstraintsExtension(false), @@ -366,8 +366,8 @@ export const InternalCertificateAuthorityFns = ({ const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id }); const appCfg = getConfig(); - const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`; - const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`; + const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/crl/${caCrl.id}/der`; + const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/ca/internal/${ca.id}/certificates/${caCert.id}/der`; const extensions: x509.Extension[] = [ new x509.BasicConstraintsExtension(false), diff --git a/backend/src/services/certificate-authority/internal/internal-certificate-authority-service.ts b/backend/src/services/certificate-authority/internal/internal-certificate-authority-service.ts index 5e42dc383..9948ddc79 100644 --- a/backend/src/services/certificate-authority/internal/internal-certificate-authority-service.ts +++ b/backend/src/services/certificate-authority/internal/internal-certificate-authority-service.ts @@ -140,7 +140,6 @@ export const internalCertificateAuthorityServiceFactory = ({ notAfter, maxPathLength, keyAlgorithm, - enableDirectIssuance, name, ...dto }: TCreateCaDTO) => { @@ -192,9 +191,9 @@ export const internalCertificateAuthorityServiceFactory = ({ const ca = await certificateAuthorityDAL.create( { projectId, - enableDirectIssuance, name: name || slugify(`${(friendlyName || dn).slice(0, 16)}-${alphaNumericNanoId(8)}`), - status: type === InternalCaType.ROOT ? CaStatus.ACTIVE : CaStatus.PENDING_CERTIFICATE + status: type === InternalCaType.ROOT ? CaStatus.ACTIVE : CaStatus.PENDING_CERTIFICATE, + enableDirectIssuance: false }, tx ); @@ -354,7 +353,7 @@ export const internalCertificateAuthorityServiceFactory = ({ * Update CA with id [caId]. * Note: Used to enable/disable CA */ - const updateCaById = async ({ caId, status, enableDirectIssuance, name, ...dto }: TUpdateCaDTO) => { + const updateCaById = async ({ caId, status, name, ...dto }: TUpdateCaDTO) => { const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId); if (!ca.internalCa) throw new NotFoundError({ message: `CA with ID '${caId}' not found` }); @@ -375,8 +374,8 @@ export const internalCertificateAuthorityServiceFactory = ({ } const updatedCa = await certificateAuthorityDAL.transaction(async (tx) => { - if (enableDirectIssuance !== undefined || status !== undefined || name !== undefined) { - await certificateAuthorityDAL.updateById(ca.id, { enableDirectIssuance, status, name }, tx); + if (status !== undefined || name !== undefined) { + await certificateAuthorityDAL.updateById(ca.id, { status, name }, tx); } return certificateAuthorityDAL.findByIdWithAssociatedCa(caId, tx); @@ -971,9 +970,9 @@ export const internalCertificateAuthorityServiceFactory = ({ const serialNumber = createSerialNumber(); const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id }); - const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`; + const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/crl/${caCrl.id}/der`; - const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`; + const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/ca/internal/${ca.id}/certificates/${caCert.id}/der`; const intermediateCert = await x509.X509CertificateGenerator.create({ serialNumber, subject: csrObj.subject, @@ -1352,8 +1351,8 @@ export const internalCertificateAuthorityServiceFactory = ({ const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id }); const appCfg = getConfig(); - const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`; - const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`; + const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/crl/${caCrl.id}/der`; + const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/ca/internal/${ca.id}/certificates/${caCert.id}/der`; const extensions: x509.Extension[] = [ new x509.BasicConstraintsExtension(false), @@ -1728,9 +1727,9 @@ export const internalCertificateAuthorityServiceFactory = ({ }); const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id }); - const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`; + const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/crl/${caCrl.id}/der`; - const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`; + const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/ca/internal/${ca.id}/certificates/${caCert.id}/der`; const extensions: x509.Extension[] = [ new x509.BasicConstraintsExtension(false), await x509.AuthorityKeyIdentifierExtension.create(caCertObj, false), diff --git a/backend/src/services/certificate-authority/internal/internal-certificate-authority-types.ts b/backend/src/services/certificate-authority/internal/internal-certificate-authority-types.ts index b4b037933..8f4e9c0d6 100644 --- a/backend/src/services/certificate-authority/internal/internal-certificate-authority-types.ts +++ b/backend/src/services/certificate-authority/internal/internal-certificate-authority-types.ts @@ -48,7 +48,6 @@ export type TCreateCaDTO = notAfter?: string; maxPathLength?: number | null; keyAlgorithm: CertKeyAlgorithm; - enableDirectIssuance: boolean; } | ({ isInternal: false; @@ -66,7 +65,6 @@ export type TCreateCaDTO = notAfter?: string; maxPathLength?: number | null; keyAlgorithm: CertKeyAlgorithm; - enableDirectIssuance: boolean; } & Omit); export type TGetCaDTO = { @@ -79,14 +77,12 @@ export type TUpdateCaDTO = caId: string; name?: string; status?: CaStatus; - enableDirectIssuance?: boolean; } | ({ isInternal: false; caId: string; name?: string; status?: CaStatus; - enableDirectIssuance?: boolean; } & Omit); export type TDeleteCaDTO = { diff --git a/backend/src/services/certificate-v3/certificate-v3-service.ts b/backend/src/services/certificate-v3/certificate-v3-service.ts index 0fadbc8de..b648b5478 100644 --- a/backend/src/services/certificate-v3/certificate-v3-service.ts +++ b/backend/src/services/certificate-v3/certificate-v3-service.ts @@ -1190,7 +1190,7 @@ export const certificateV3ServiceFactory = ({ status: CertificateOrderStatus.VALID })), authorizations: [], - finalize: `/api/v3/pki/certificates/orders/${orderId}/completed`, + finalize: `/api/v1/cert-manager/certificates/orders/${orderId}/completed`, certificate: certificateResult.certificate, projectId: certificateResult.projectId, profileName: certificateResult.profileName diff --git a/backend/src/services/certificate/certificate-service.ts b/backend/src/services/certificate/certificate-service.ts index 515ee3ee0..983bf3f46 100644 --- a/backend/src/services/certificate/certificate-service.ts +++ b/backend/src/services/certificate/certificate-service.ts @@ -52,7 +52,10 @@ import { } from "./certificate-types"; type TCertificateServiceFactoryDep = { - certificateDAL: Pick; + certificateDAL: Pick< + TCertificateDALFactory, + "findOne" | "deleteById" | "update" | "find" | "transaction" | "create" | "findById" + >; certificateSecretDAL: Pick; certificateBodyDAL: Pick; certificateAuthorityDAL: Pick; @@ -91,8 +94,8 @@ export const certificateServiceFactory = ({ /** * Return details for certificate with serial number [serialNumber] */ - const getCert = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertDTO) => { - const cert = await certificateDAL.findOne({ serialNumber }); + const getCert = async ({ id, serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertDTO) => { + const cert = id ? await certificateDAL.findById(id) : await certificateDAL.findOne({ serialNumber }); const { permission } = await permissionService.getProjectPermission({ actor, @@ -117,13 +120,14 @@ export const certificateServiceFactory = ({ * Get certificate private key. */ const getCertPrivateKey = async ({ + id, serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertPrivateKeyDTO) => { - const cert = await certificateDAL.findOne({ serialNumber }); + const cert = id ? await certificateDAL.findById(id) : await certificateDAL.findOne({ serialNumber }); const { permission } = await permissionService.getProjectPermission({ actor, @@ -156,8 +160,8 @@ export const certificateServiceFactory = ({ /** * Delete certificate with serial number [serialNumber] */ - const deleteCert = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteCertDTO) => { - const cert = await certificateDAL.findOne({ serialNumber }); + const deleteCert = async ({ id, serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteCertDTO) => { + const cert = id ? await certificateDAL.findById(id) : await certificateDAL.findOne({ serialNumber }); const { permission } = await permissionService.getProjectPermission({ actor, @@ -193,6 +197,7 @@ export const certificateServiceFactory = ({ * of its issuing CA */ const revokeCert = async ({ + id, serialNumber, revocationReason, actorId, @@ -200,7 +205,7 @@ export const certificateServiceFactory = ({ actor, actorOrgId }: TRevokeCertDTO) => { - const cert = await certificateDAL.findOne({ serialNumber }); + const cert = id ? await certificateDAL.findById(id) : await certificateDAL.findOne({ serialNumber }); if (!cert.caId) { throw new BadRequestError({ @@ -290,8 +295,8 @@ export const certificateServiceFactory = ({ * Return certificate body and certificate chain for certificate with * serial number [serialNumber] */ - const getCertBody = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertBodyDTO) => { - const cert = await certificateDAL.findOne({ serialNumber }); + const getCertBody = async ({ id, serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertBodyDTO) => { + const cert = id ? await certificateDAL.findById(id) : await certificateDAL.findOne({ serialNumber }); const { permission } = await permissionService.getProjectPermission({ actor, @@ -584,8 +589,15 @@ export const certificateServiceFactory = ({ * Return certificate body and certificate chain for certificate with * serial number [serialNumber] */ - const getCertBundle = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertBundleDTO) => { - const cert = await certificateDAL.findOne({ serialNumber }); + const getCertBundle = async ({ + id, + serialNumber, + actorId, + actorAuthMethod, + actor, + actorOrgId + }: TGetCertBundleDTO) => { + const cert = id ? await certificateDAL.findById(id) : await certificateDAL.findOne({ serialNumber }); const { permission } = await permissionService.getProjectPermission({ actor, @@ -673,12 +685,13 @@ export const certificateServiceFactory = ({ certificate, certificateChain, privateKey, - serialNumber, + serialNumber: cert.serialNumber, cert }; }; const getCertPkcs12 = async ({ + id, serialNumber, password, alias, @@ -700,7 +713,7 @@ export const certificateServiceFactory = ({ if (!alias || alias.trim() === "") { throw new BadRequestError({ message: "Alias is required for PKCS12 keystore generation" }); } - const cert = await certificateDAL.findOne({ serialNumber }); + const cert = id ? await certificateDAL.findById(id) : await certificateDAL.findOne({ serialNumber }); const { permission } = await permissionService.getProjectPermission({ actor, diff --git a/backend/src/services/certificate/certificate-types.ts b/backend/src/services/certificate/certificate-types.ts index 085bb9588..6c9d8b6bc 100644 --- a/backend/src/services/certificate/certificate-types.ts +++ b/backend/src/services/certificate/certificate-types.ts @@ -84,20 +84,24 @@ export enum CrlReason { } export type TGetCertDTO = { - serialNumber: string; + id?: string; + serialNumber?: string; } & Omit; export type TDeleteCertDTO = { - serialNumber: string; + id?: string; + serialNumber?: string; } & Omit; export type TRevokeCertDTO = { - serialNumber: string; + id?: string; + serialNumber?: string; revocationReason: CrlReason; } & Omit; export type TGetCertBodyDTO = { - serialNumber: string; + id?: string; + serialNumber?: string; } & Omit; export type TImportCertDTO = { @@ -112,15 +116,18 @@ export type TImportCertDTO = { } & Omit; export type TGetCertPrivateKeyDTO = { - serialNumber: string; + id?: string; + serialNumber?: string; } & Omit; export type TGetCertBundleDTO = { - serialNumber: string; + id?: string; + serialNumber?: string; } & Omit; export type TGetCertPkcs12DTO = { - serialNumber: string; + id?: string; + serialNumber?: string; password: string; alias: string; } & Omit; diff --git a/backend/src/services/pki-subscriber/pki-subscriber-service.ts b/backend/src/services/pki-subscriber/pki-subscriber-service.ts index ebb1ef599..738819fc6 100644 --- a/backend/src/services/pki-subscriber/pki-subscriber-service.ts +++ b/backend/src/services/pki-subscriber/pki-subscriber-service.ts @@ -524,8 +524,8 @@ export const pkiSubscriberServiceFactory = ({ }); const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id }); - const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`; - const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`; + const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/crl/${caCrl.id}/der`; + const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/ca/internal/${ca.id}/certificates/${caCert.id}/der`; const extensions: x509.Extension[] = [ new x509.BasicConstraintsExtension(false), diff --git a/backend/src/services/pki-templates/pki-templates-service.ts b/backend/src/services/pki-templates/pki-templates-service.ts index e648ab88f..82d856e25 100644 --- a/backend/src/services/pki-templates/pki-templates-service.ts +++ b/backend/src/services/pki-templates/pki-templates-service.ts @@ -466,8 +466,8 @@ export const pkiTemplatesServiceFactory = ({ }); const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id }); - const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`; - const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`; + const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/crl/${caCrl.id}/der`; + const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/cert-manager/ca/internal/${ca.id}/certificates/${caCert.id}/der`; const extensions: x509.Extension[] = [ new x509.BasicConstraintsExtension(false), diff --git a/frontend/src/const/routes.ts b/frontend/src/const/routes.ts index 74fe9f29e..6046c8fc8 100644 --- a/frontend/src/const/routes.ts +++ b/frontend/src/const/routes.ts @@ -294,8 +294,8 @@ export const ROUTE_PATHS = Object.freeze({ }, CertManager: { CertAuthDetailsByIDPage: setRoute( - "/organizations/$orgId/projects/cert-management/$projectId/ca/$caName", - "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName" + "/organizations/$orgId/projects/cert-management/$projectId/ca/$caId", + "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId" ), SubscribersPage: setRoute( "/organizations/$orgId/projects/cert-management/$projectId/subscribers", diff --git a/frontend/src/hooks/api/ca/index.tsx b/frontend/src/hooks/api/ca/index.tsx index 05a161c75..04a44dbd6 100644 --- a/frontend/src/hooks/api/ca/index.tsx +++ b/frontend/src/hooks/api/ca/index.tsx @@ -13,12 +13,12 @@ export { export { useGetAzureAdcsTemplates, useGetCa, - useGetCaById, useGetCaCert, useGetCaCerts, useGetCaCertTemplates, useGetCaCrls, useGetCaCsr, + useGetInternalCaById, useListCasByProjectId, useListCasByTypeAndProjectId, useListExternalCasByProjectId diff --git a/frontend/src/hooks/api/ca/mutations.tsx b/frontend/src/hooks/api/ca/mutations.tsx index e19069984..e87e1cf2d 100644 --- a/frontend/src/hooks/api/ca/mutations.tsx +++ b/frontend/src/hooks/api/ca/mutations.tsx @@ -27,21 +27,20 @@ import { export const useUpdateCa = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: async ({ caName, ...body }) => { + mutationFn: async ({ id, ...body }) => { const { data } = await apiRequest.patch( - `/api/v1/pki/ca/${body.type}/${caName}`, + `/api/v1/cert-manager/ca/${body.type}/${id}`, body ); return data; }, - onSuccess: ({ projectId, type }, { caName }) => { - caKeys.getCaByNameAndProjectId(caName, projectId); + onSuccess: ({ projectId, type }, { id }) => { queryClient.invalidateQueries({ queryKey: caKeys.listCasByTypeAndProjectId(type, projectId) }); queryClient.invalidateQueries({ - queryKey: caKeys.getCaByNameAndProjectId(caName, projectId) + queryKey: caKeys.getCaById(id) }); // Invalidate external CAs list queryClient.invalidateQueries({ @@ -56,7 +55,7 @@ export const useCreateCa = () => { return useMutation({ mutationFn: async (body) => { const { data } = await apiRequest.post( - `/api/v1/pki/ca/${body.type}`, + `/api/v1/cert-manager/ca/${body.type}`, body ); return data; @@ -76,14 +75,9 @@ export const useCreateCa = () => { export const useDeleteCa = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: async ({ caName, type, projectId }) => { + mutationFn: async ({ id, type }) => { const { data } = await apiRequest.delete( - `/api/v1/pki/ca/${type}/${caName}`, - { - data: { - projectId - } - } + `/api/v1/cert-manager/ca/${type}/${id}` ); return data; }, @@ -104,7 +98,7 @@ export const useSignIntermediate = () => { return useMutation({ mutationFn: async (body) => { const { data } = await apiRequest.post( - `/api/v1/pki/ca/${body.caId}/sign-intermediate`, + `/api/v1/cert-manager/ca/internal/${body.caId}/sign-intermediate`, body ); return data; @@ -117,13 +111,14 @@ export const useImportCaCertificate = (projectId: string) => { return useMutation({ mutationFn: async ({ caId, ...body }) => { const { data } = await apiRequest.post( - `/api/v1/pki/ca/${caId}/import-certificate`, + `/api/v1/cert-manager/ca/internal/${caId}/import-certificate`, body ); return data; }, onSuccess: (_, { caId }) => { queryClient.invalidateQueries({ queryKey: projectKeys.getProjectCas({ projectId }) }); + queryClient.invalidateQueries({ queryKey: caKeys.getCaById(caId) }); queryClient.invalidateQueries({ queryKey: caKeys.getCaCerts(caId) }); queryClient.invalidateQueries({ queryKey: caKeys.getCaCert(caId) }); queryClient.invalidateQueries({ @@ -133,7 +128,7 @@ export const useImportCaCertificate = (projectId: string) => { }); }; -// consider rename to issue certificate +// TODO: DEPRECATE export const useCreateCertificate = () => { const queryClient = useQueryClient(); return useMutation({ @@ -157,7 +152,7 @@ export const useCreateCertificateV3 = (options?: { projectId?: string }) => { return useMutation({ mutationFn: async (body) => { const { data } = await apiRequest.post( - "/api/v3/pki/certificates/issue-certificate", + "/api/v1/cert-manager/certificates/issue-certificate", body ); return data; @@ -185,7 +180,7 @@ export const useOrderCertificateWithProfile = () => { return useMutation({ mutationFn: async (body) => { const { data } = await apiRequest.post( - "/api/v3/pki/certificates/order-certificate", + "/api/v1/cert-manager/certificates/order-certificate", body ); return data; @@ -203,7 +198,7 @@ export const useRenewCa = () => { return useMutation({ mutationFn: async (body) => { const { data } = await apiRequest.post( - `/api/v1/pki/ca/${body.caId}/renew`, + `/api/v1/cert-manager/ca/internal/${body.caId}/renew`, body ); return data; diff --git a/frontend/src/hooks/api/ca/queries.tsx b/frontend/src/hooks/api/ca/queries.tsx index 68e8d2c12..09e4c0f3b 100644 --- a/frontend/src/hooks/api/ca/queries.tsx +++ b/frontend/src/hooks/api/ca/queries.tsx @@ -4,7 +4,11 @@ import { apiRequest } from "@app/config/request"; import { TCertificateTemplate } from "../certificateTemplates/types"; import { CaType } from "./enums"; -import { TAzureAdCsTemplate, TCertificateAuthority, TUnifiedCertificateAuthority } from "./types"; +import { + TAzureAdCsTemplate, + TInternalCertificateAuthority, + TUnifiedCertificateAuthority +} from "./types"; export const caKeys = { getCaById: (caId: string) => [{ caId }, "ca"], @@ -25,24 +29,16 @@ export const caKeys = { ] }; -export const useGetCa = ({ - caName, - projectId, - type -}: { - caName: string; - projectId: string; - type: CaType; -}) => { +export const useGetCa = ({ caId, type }: { caId: string; type: CaType }) => { return useQuery({ - queryKey: caKeys.getCaByNameAndProjectId(caName, projectId), + queryKey: caKeys.getCaById(caId), queryFn: async () => { const { data } = await apiRequest.get( - `/api/v1/pki/ca/${type}/${caName}?projectId=${projectId}` + `/api/v1/cert-manager/ca/${type}/${caId}` ); return data; }, - enabled: Boolean(caName && projectId && type) + enabled: Boolean(caId && type) }); }; @@ -51,7 +47,7 @@ export const useListCasByTypeAndProjectId = (type: CaType, projectId: string) => queryKey: caKeys.listCasByTypeAndProjectId(type, projectId), queryFn: async () => { const { data } = await apiRequest.get( - `/api/v1/pki/ca/${type}?projectId=${projectId}` + `/api/v1/cert-manager/ca/${type}?projectId=${projectId}` ); return data; @@ -65,7 +61,7 @@ export const useListCasByProjectId = (projectId: string) => { queryFn: async () => { const { data } = await apiRequest.get<{ certificateAuthorities: TUnifiedCertificateAuthority[]; - }>(`/api/v2/pki/ca?projectId=${projectId}`); + }>(`/api/v1/cert-manager/ca?projectId=${projectId}`); return data.certificateAuthorities; } @@ -78,10 +74,10 @@ export const useListExternalCasByProjectId = (projectId: string) => { queryFn: async () => { const [acmeResponse, azureAdCsResponse] = await Promise.allSettled([ apiRequest.get( - `/api/v1/pki/ca/${CaType.ACME}?projectId=${projectId}` + `/api/v1/cert-manager/ca/${CaType.ACME}?projectId=${projectId}` ), apiRequest.get( - `/api/v1/pki/ca/${CaType.AZURE_AD_CS}?projectId=${projectId}` + `/api/v1/cert-manager/ca/${CaType.AZURE_AD_CS}?projectId=${projectId}` ) ]); @@ -100,14 +96,14 @@ export const useListExternalCasByProjectId = (projectId: string) => { }); }; -export const useGetCaById = (caId: string) => { +export const useGetInternalCaById = (caId: string) => { return useQuery({ queryKey: caKeys.getCaById(caId), queryFn: async () => { - const { - data: { ca } - } = await apiRequest.get<{ ca: TCertificateAuthority }>(`/api/v1/pki/ca/${caId}`); - return ca; + const { data } = await apiRequest.get( + `/api/v1/cert-manager/ca/internal/${caId}` + ); + return data; }, enabled: Boolean(caId) }); @@ -124,7 +120,7 @@ export const useGetCaCerts = (caId: string) => { serialNumber: string; version: number; }[] - >(`/api/v1/pki/ca/${caId}/ca-certificates`); // TODO: consider updating endpoint structure + >(`/api/v1/cert-manager/ca/internal/${caId}/ca-certificates`); return data; }, enabled: Boolean(caId) @@ -139,7 +135,7 @@ export const useGetCaCert = (caId: string) => { certificate: string; certificateChain: string; serialNumber: string; - }>(`/api/v1/pki/ca/${caId}/certificate`); // TODO: consider updating endpoint structure + }>(`/api/v1/cert-manager/ca/internal/${caId}/certificate`); return data; }, enabled: Boolean(caId) @@ -154,7 +150,7 @@ export const useGetCaCsr = (caId: string) => { data: { csr } } = await apiRequest.get<{ csr: string; - }>(`/api/v1/pki/ca/${caId}/csr`); + }>(`/api/v1/cert-manager/ca/internal/${caId}/csr`); return csr; }, enabled: Boolean(caId) @@ -170,13 +166,14 @@ export const useGetCaCrls = (caId: string) => { id: string; crl: string; }[] - >(`/api/v1/pki/ca/${caId}/crls`); + >(`/api/v1/cert-manager/ca/internal/${caId}/crls`); return data; }, enabled: Boolean(caId) }); }; +// TODO: DEPRECATE export const useGetCaCertTemplates = (caId: string) => { return useQuery({ queryKey: caKeys.getCaCertTemplates(caId), @@ -202,7 +199,7 @@ export const useGetAzureAdcsTemplates = ({ queryFn: async () => { const { data } = await apiRequest.get<{ templates: TAzureAdCsTemplate[]; - }>(`/api/v1/pki/ca/azure-ad-cs/${caId}/templates?projectId=${projectId}`); + }>(`/api/v1/cert-manager/ca/azure-ad-cs/${caId}/templates?projectId=${projectId}`); return data; }, enabled: Boolean(caId && projectId) diff --git a/frontend/src/hooks/api/ca/types.ts b/frontend/src/hooks/api/ca/types.ts index 31d35e904..a07499975 100644 --- a/frontend/src/hooks/api/ca/types.ts +++ b/frontend/src/hooks/api/ca/types.ts @@ -68,15 +68,14 @@ export type TUnifiedCertificateAuthority = export type TCreateCertificateAuthorityDTO = Omit; export type TUpdateCertificateAuthorityDTO = Partial & { - caName: string; - projectId: string; + id: string; type: CaType; }; export type TDeleteCertificateAuthorityDTO = { - caName: string; - type: CaType; + id: string; projectId: string; + type: CaType; }; export type TCertificateAuthority = { diff --git a/frontend/src/hooks/api/certificateProfiles/mutations.tsx b/frontend/src/hooks/api/certificateProfiles/mutations.tsx index ca784ed0d..8cfb04b76 100644 --- a/frontend/src/hooks/api/certificateProfiles/mutations.tsx +++ b/frontend/src/hooks/api/certificateProfiles/mutations.tsx @@ -17,7 +17,7 @@ export const useCreateCertificateProfile = () => { mutationFn: async (data) => { const { data: response } = await apiRequest.post<{ certificateProfile: TCertificateProfile; - }>("/api/v1/pki/certificate-profiles", data); + }>("/api/v1/cert-manager/certificate-profiles", data); return response.certificateProfile; }, onSuccess: (_, { projectId }) => { @@ -35,7 +35,7 @@ export const useUpdateCertificateProfile = () => { mutationFn: async ({ profileId, ...data }) => { const { data: response } = await apiRequest.patch<{ certificateProfile: TCertificateProfile; - }>(`/api/v1/pki/certificate-profiles/${profileId}`, data); + }>(`/api/v1/cert-manager/certificate-profiles/${profileId}`, data); return response.certificateProfile; }, onSuccess: (profile, { profileId }) => { @@ -56,7 +56,7 @@ export const useDeleteCertificateProfile = () => { mutationFn: async ({ profileId }) => { const { data: response } = await apiRequest.delete<{ certificateProfile: TCertificateProfile; - }>(`/api/v1/pki/certificate-profiles/${profileId}`); + }>(`/api/v1/cert-manager/certificate-profiles/${profileId}`); return response.certificateProfile; }, onSuccess: (profile, { profileId }) => { diff --git a/frontend/src/hooks/api/certificateProfiles/queries.tsx b/frontend/src/hooks/api/certificateProfiles/queries.tsx index 1e0fe3b9b..71f0e6ce9 100644 --- a/frontend/src/hooks/api/certificateProfiles/queries.tsx +++ b/frontend/src/hooks/api/certificateProfiles/queries.tsx @@ -71,7 +71,7 @@ export const useListCertificateProfiles = ({ const { data } = await apiRequest.get<{ certificateProfiles: TCertificateProfile[]; totalCount: number; - }>("/api/v1/pki/certificate-profiles", { + }>("/api/v1/cert-manager/certificate-profiles", { params: { projectId, limit, @@ -93,7 +93,7 @@ export const useGetCertificateProfileById = ({ profileId }: TGetCertificateProfi queryFn: async () => { const { data } = await apiRequest.get<{ certificateProfile: TCertificateProfileWithDetails; - }>(`/api/v1/pki/certificate-profiles/${profileId}`); + }>(`/api/v1/cert-manager/certificate-profiles/${profileId}`); return data.certificateProfile; }, enabled: Boolean(profileId) @@ -109,7 +109,7 @@ export const useGetCertificateProfileBySlug = ({ queryFn: async () => { const { data } = await apiRequest.get<{ certificateProfile: TCertificateProfile; - }>(`/api/v1/pki/certificate-profiles/slug/${slug}`, { + }>(`/api/v1/cert-manager/certificate-profiles/slug/${slug}`, { params: { projectId } }); return data.certificateProfile; @@ -125,7 +125,7 @@ export const useRevealAcmeEabSecret = ({ profileId }: TRevealAcmeEabSecretDTO) = const { data } = await apiRequest.get<{ eabKid: string; eabSecret: string; - }>(`/api/v1/pki/certificate-profiles/${profileId}/acme/eab-secret/reveal`); + }>(`/api/v1/cert-manager/certificate-profiles/${profileId}/acme/eab-secret/reveal`); return data; }, enabled: Boolean(profileId) @@ -144,7 +144,7 @@ export const useGetProfileCertificates = ({ queryFn: async () => { const { data } = await apiRequest.get<{ certificates: TProfileCertificate[]; - }>(`/api/v1/pki/certificate-profiles/${profileId}/certificates`, { + }>(`/api/v1/cert-manager/certificate-profiles/${profileId}/certificates`, { params: { offset, limit, diff --git a/frontend/src/hooks/api/certificateTemplates/mutations.tsx b/frontend/src/hooks/api/certificateTemplates/mutations.tsx index 998194ddc..d4647d5ee 100644 --- a/frontend/src/hooks/api/certificateTemplates/mutations.tsx +++ b/frontend/src/hooks/api/certificateTemplates/mutations.tsx @@ -21,6 +21,7 @@ import { TUpdateEstConfigDTO } from "./types"; +// TODO: DEPRECATE export const useCreateCertTemplate = () => { const queryClient = useQueryClient(); return useMutation({ @@ -40,6 +41,7 @@ export const useCreateCertTemplate = () => { }); }; +// TODO: DEPRECATE export const useUpdateCertTemplate = () => { const queryClient = useQueryClient(); return useMutation({ @@ -61,6 +63,7 @@ export const useUpdateCertTemplate = () => { }); }; +// TODO: DEPRECATE export const useDeleteCertTemplate = () => { const queryClient = useQueryClient(); return useMutation({ @@ -86,7 +89,7 @@ export const useCreateCertTemplateV2 = () => { mutationFn: async (dto) => { const { data } = await apiRequest.post<{ certificateTemplate: TCertificateTemplate; - }>("/api/v2/pki/certificate-templates", dto); + }>("/api/v1/cert-manager/certificate-templates", dto); return data.certificateTemplate; }, onSuccess: (_, { projectId }) => { @@ -105,7 +108,7 @@ export const useUpdateCertTemplateV2 = () => { return useMutation({ mutationFn: async (dto) => { const { data } = await apiRequest.patch<{ certificateTemplate: TCertificateTemplate }>( - `/api/v2/pki/certificate-templates/${dto.templateName}`, + `/api/v1/cert-manager/certificate-templates/${dto.templateName}`, dto ); @@ -127,7 +130,7 @@ export const useDeleteCertTemplateV2 = () => { return useMutation({ mutationFn: async (dto) => { const { data } = await apiRequest.delete<{ certificateTemplate: TCertificateTemplate }>( - `/api/v2/pki/certificate-templates/${dto.templateName}`, + `/api/v1/cert-manager/certificate-templates/${dto.templateName}`, { data: { projectId: dto.projectId @@ -147,6 +150,7 @@ export const useDeleteCertTemplateV2 = () => { }); }; +// TODO: DEPRECATE export const useCreateEstConfig = () => { const queryClient = useQueryClient(); return useMutation({ @@ -165,6 +169,7 @@ export const useCreateEstConfig = () => { }); }; +// TODO: DEPRECATE export const useUpdateEstConfig = () => { const queryClient = useQueryClient(); return useMutation({ @@ -193,7 +198,7 @@ export const useCreateCertificateTemplateV2WithPolicies = () => { mutationFn: async (data) => { const { data: response } = await apiRequest.post<{ certificateTemplate: TCertificateTemplateV2WithPolicies; - }>("/api/v2/certificate-templates", data); + }>("/api/v1/cert-manager/certificate-templates", data); return response.certificateTemplate; }, onSuccess: (_, { projectId }) => { @@ -214,7 +219,7 @@ export const useUpdateCertificateTemplateV2WithPolicies = () => { mutationFn: async ({ templateId, ...data }) => { const { data: response } = await apiRequest.patch<{ certificateTemplate: TCertificateTemplateV2WithPolicies; - }>(`/api/v2/certificate-templates/${templateId}`, data); + }>(`/api/v1/cert-manager/certificate-templates/${templateId}`, data); return response.certificateTemplate; }, onSuccess: (template, { templateId }) => { @@ -238,7 +243,7 @@ export const useDeleteCertificateTemplateV2WithPolicies = () => { mutationFn: async ({ templateId }) => { const { data: response } = await apiRequest.delete<{ certificateTemplate: TCertificateTemplateV2WithPolicies; - }>(`/api/v2/certificate-templates/${templateId}`); + }>(`/api/v1/cert-manager/certificate-templates/${templateId}`); return response.certificateTemplate; }, onSuccess: (template, { templateId }) => { diff --git a/frontend/src/hooks/api/certificateTemplates/queries.tsx b/frontend/src/hooks/api/certificateTemplates/queries.tsx index 383f4ed71..4b823f296 100644 --- a/frontend/src/hooks/api/certificateTemplates/queries.tsx +++ b/frontend/src/hooks/api/certificateTemplates/queries.tsx @@ -31,6 +31,7 @@ export const certTemplateKeys = { getTemplateV2ById: (id: string) => ["cert-template-v2", id] }; +// TODO: DEPRECATE export const useGetCertTemplate = (id: string) => { return useQuery({ queryKey: certTemplateKeys.getCertTemplateById(id), @@ -44,6 +45,7 @@ export const useGetCertTemplate = (id: string) => { }); }; +// TODO: DEPRECATE export const useListCertificateTemplates = ({ limit = 100, offset = 0, @@ -55,7 +57,7 @@ export const useListCertificateTemplates = ({ const { data } = await apiRequest.get<{ certificateTemplates: TCertificateTemplateV2[]; totalCount?: number; - }>("/api/v2/pki/certificate-templates", { + }>("/api/v1/pki/certificate-templates", { params: { limit, offset, @@ -67,6 +69,7 @@ export const useListCertificateTemplates = ({ }); }; +// TODO: DEPRECATE export const useGetEstConfig = (certificateTemplateId: string) => { return useQuery({ queryKey: certTemplateKeys.getEstConfig(certificateTemplateId), @@ -92,7 +95,7 @@ export const useListCertificateTemplatesV2 = ({ const { data } = await apiRequest.get<{ certificateTemplates: TCertificateTemplateV2WithPolicies[]; totalCount: number; - }>("/api/v2/certificate-templates", { + }>("/api/v1/cert-manager/certificate-templates", { params: { projectId, limit, @@ -113,7 +116,7 @@ export const useGetCertificateTemplateV2ById = ({ queryFn: async () => { const { data } = await apiRequest.get<{ certificateTemplate: TCertificateTemplateV2WithPolicies; - }>(`/api/v2/certificate-templates/${templateId}`); + }>(`/api/v1/cert-manager/certificate-templates/${templateId}`); return data.certificateTemplate; }, enabled: Boolean(templateId) diff --git a/frontend/src/hooks/api/certificates/mutations.tsx b/frontend/src/hooks/api/certificates/mutations.tsx index f65d6adc6..aca752458 100644 --- a/frontend/src/hooks/api/certificates/mutations.tsx +++ b/frontend/src/hooks/api/certificates/mutations.tsx @@ -19,11 +19,11 @@ import { export const useDeleteCert = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: async ({ serialNumber }) => { + mutationFn: async ({ id }) => { const { data: { certificate } } = await apiRequest.delete<{ certificate: TCertificate }>( - `/api/v1/pki/certificates/${serialNumber}` + `/api/v1/cert-manager/certificates/${id}` ); return certificate; }, @@ -47,11 +47,11 @@ export const useDeleteCert = () => { export const useRevokeCert = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: async ({ serialNumber, revocationReason }) => { + mutationFn: async ({ id, revocationReason }) => { const { data: { certificate } } = await apiRequest.post<{ certificate: TCertificate }>( - `/api/v1/pki/certificates/${serialNumber}/revoke`, + `/api/v1/cert-manager/certificates/${id}/revoke`, { revocationReason } @@ -80,7 +80,7 @@ export const useImportCertificate = () => { return useMutation({ mutationFn: async (body) => { const { data } = await apiRequest.post( - "/api/v1/pki/certificates/import-certificate", + "/api/v1/cert-manager/certificates/import-certificate", body ); return data; @@ -98,7 +98,7 @@ export const useRenewCertificate = () => { return useMutation({ mutationFn: async ({ certificateId }) => { const { data } = await apiRequest.post( - `/api/v3/pki/certificates/${certificateId}/renew`, + `/api/v1/cert-manager/certificates/${certificateId}/renew`, {} ); return data; @@ -131,7 +131,7 @@ export const useUpdateRenewalConfig = () => { >({ mutationFn: async ({ certificateId, renewBeforeDays, enableAutoRenewal }) => { const { data } = await apiRequest.patch<{ message: string; renewBeforeDays?: number }>( - `/api/v3/pki/certificates/${certificateId}/config`, + `/api/v1/cert-manager/certificates/${certificateId}/config`, { renewBeforeDays, enableAutoRenewal } ); return data; @@ -152,7 +152,7 @@ export const useDownloadCertPkcs12 = () => { mutationFn: async ({ serialNumber, projectSlug, password, alias }) => { try { const response = await apiRequest.post( - `/api/v1/pki/certificates/${serialNumber}/pkcs12`, + `/api/v1/cert-manager/certificates/${serialNumber}/pkcs12`, { password, alias diff --git a/frontend/src/hooks/api/certificates/types.ts b/frontend/src/hooks/api/certificates/types.ts index ee543aac7..953ae818f 100644 --- a/frontend/src/hooks/api/certificates/types.ts +++ b/frontend/src/hooks/api/certificates/types.ts @@ -24,13 +24,13 @@ export type TCertificate = { }; export type TDeleteCertDTO = { + id: string; projectId: string; - serialNumber: string; }; export type TRevokeCertDTO = { projectId: string; - serialNumber: string; + id: string; revocationReason: string; }; diff --git a/frontend/src/hooks/api/pkiAlerts/mutations.tsx b/frontend/src/hooks/api/pkiAlerts/mutations.tsx index df48a6aab..5c41dd619 100644 --- a/frontend/src/hooks/api/pkiAlerts/mutations.tsx +++ b/frontend/src/hooks/api/pkiAlerts/mutations.tsx @@ -6,6 +6,7 @@ import { projectKeys } from "../projects"; import { pkiAlertKeys } from "./queries"; import { TCreatePkiAlertDTO, TDeletePkiAlertDTO, TPkiAlert, TUpdatePkiAlertDTO } from "./types"; +// TODO: DEPRECATE export const useCreatePkiAlert = () => { const queryClient = useQueryClient(); return useMutation({ @@ -19,6 +20,7 @@ export const useCreatePkiAlert = () => { }); }; +// TODO: DEPRECATE export const useUpdatePkiAlert = () => { const queryClient = useQueryClient(); return useMutation({ @@ -36,6 +38,7 @@ export const useUpdatePkiAlert = () => { }); }; +// TODO: DEPRECATE export const useDeletePkiAlert = () => { const queryClient = useQueryClient(); return useMutation({ diff --git a/frontend/src/hooks/api/pkiAlerts/queries.tsx b/frontend/src/hooks/api/pkiAlerts/queries.tsx index db324e96d..01db5ea51 100644 --- a/frontend/src/hooks/api/pkiAlerts/queries.tsx +++ b/frontend/src/hooks/api/pkiAlerts/queries.tsx @@ -8,6 +8,7 @@ export const pkiAlertKeys = { getPkiAlertById: (alertId: string) => [{ alertId }, "alert"] }; +// TODO: DEPRECATE export const useGetPkiAlertById = (alertId: string) => { return useQuery({ queryKey: pkiAlertKeys.getPkiAlertById(alertId), diff --git a/frontend/src/hooks/api/pkiAlertsV2/mutations.ts b/frontend/src/hooks/api/pkiAlertsV2/mutations.ts index 7092cf7b5..e9159550f 100644 --- a/frontend/src/hooks/api/pkiAlertsV2/mutations.ts +++ b/frontend/src/hooks/api/pkiAlertsV2/mutations.ts @@ -11,7 +11,7 @@ export const useCreatePkiAlertV2 = () => { return useMutation({ mutationFn: async (data) => { const { data: response } = await apiRequest.post<{ alert: TPkiAlertV2 }>( - "/api/v2/pki/alerts", + "/api/v1/cert-manager/alerts", data ); return response.alert; @@ -30,7 +30,7 @@ export const useUpdatePkiAlertV2 = () => { return useMutation({ mutationFn: async ({ alertId, ...data }) => { const { data: response } = await apiRequest.patch<{ alert: TPkiAlertV2 }>( - `/api/v2/pki/alerts/${alertId}`, + `/api/v1/cert-manager/alerts/${alertId}`, data ); return response.alert; @@ -52,7 +52,7 @@ export const useDeletePkiAlertV2 = () => { return useMutation({ mutationFn: async ({ alertId }) => { const { data } = await apiRequest.delete<{ alert: TPkiAlertV2 }>( - `/api/v2/pki/alerts/${alertId}` + `/api/v1/cert-manager/alerts/${alertId}` ); return data.alert; }, diff --git a/frontend/src/hooks/api/pkiAlertsV2/queries.ts b/frontend/src/hooks/api/pkiAlertsV2/queries.ts index d139341ae..a4ca9006f 100644 --- a/frontend/src/hooks/api/pkiAlertsV2/queries.ts +++ b/frontend/src/hooks/api/pkiAlertsV2/queries.ts @@ -24,14 +24,16 @@ export const pkiAlertsV2Keys = { }; const fetchPkiAlertsV2 = async (params: TGetPkiAlertsV2): Promise => { - const { data } = await apiRequest.get("/api/v2/pki/alerts", { + const { data } = await apiRequest.get("/api/v1/cert-manager/alerts", { params }); return data; }; const fetchPkiAlertV2ById = async ({ alertId }: TGetPkiAlertV2ById): Promise => { - const { data } = await apiRequest.get<{ alert: TPkiAlertV2 }>(`/api/v2/pki/alerts/${alertId}`); + const { data } = await apiRequest.get<{ alert: TPkiAlertV2 }>( + `/api/v1/cert-manager/alerts/${alertId}` + ); return data.alert; }; @@ -40,7 +42,7 @@ const fetchPkiAlertV2MatchingCertificates = async ( ): Promise => { const { alertId, ...queryParams } = params; const { data } = await apiRequest.get( - `/api/v2/pki/alerts/${alertId}/certificates`, + `/api/v1/cert-manager/alerts/${alertId}/certificates`, { params: queryParams } ); return data; @@ -50,7 +52,7 @@ const fetchPkiAlertV2CurrentMatchingCertificates = async ( params: TGetPkiAlertV2CurrentMatchingCertificates ): Promise => { const { data } = await apiRequest.post( - "/api/v2/pki/alerts/preview/certificates", + "/api/v1/cert-manager/alerts/preview/certificates", params ); return data; diff --git a/frontend/src/hooks/api/pkiSyncs/mutations.tsx b/frontend/src/hooks/api/pkiSyncs/mutations.tsx index 9aff79dd0..20eb1fae8 100644 --- a/frontend/src/hooks/api/pkiSyncs/mutations.tsx +++ b/frontend/src/hooks/api/pkiSyncs/mutations.tsx @@ -17,7 +17,10 @@ export const useCreatePkiSync = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ destination, ...params }: TCreatePkiSyncDTO) => { - const { data } = await apiRequest.post(`/api/v1/pki/syncs/${destination}`, params); + const { data } = await apiRequest.post( + `/api/v1/cert-manager/syncs/${destination}`, + params + ); return data; }, @@ -31,7 +34,7 @@ export const useUpdatePkiSync = () => { return useMutation({ mutationFn: async ({ syncId, projectId, destination, ...params }: TUpdatePkiSyncDTO) => { const { data } = await apiRequest.patch( - `/api/v1/pki/syncs/${destination}/${syncId}`, + `/api/v1/cert-manager/syncs/${destination}/${syncId}`, params, { params: { projectId } } ); @@ -49,9 +52,12 @@ export const useDeletePkiSync = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ syncId, projectId, destination }: TDeletePkiSyncDTO) => { - const { data } = await apiRequest.delete(`/api/v1/pki/syncs/${destination}/${syncId}`, { - params: { projectId } - }); + const { data } = await apiRequest.delete( + `/api/v1/cert-manager/syncs/${destination}/${syncId}`, + { + params: { projectId } + } + ); return data; }, @@ -66,7 +72,9 @@ export const useTriggerPkiSyncSyncCertificates = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ syncId, destination }: TTriggerPkiSyncSyncCertificatesDTO) => { - const { data } = await apiRequest.post(`/api/v1/pki/syncs/${destination}/${syncId}/sync`); + const { data } = await apiRequest.post( + `/api/v1/cert-manager/syncs/${destination}/${syncId}/sync` + ); return data; }, @@ -111,7 +119,9 @@ export const useTriggerPkiSyncImportCertificates = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ syncId, destination }: TTriggerPkiSyncImportCertificatesDTO) => { - const { data } = await apiRequest.post(`/api/v1/pki/syncs/${destination}/${syncId}/import`); + const { data } = await apiRequest.post( + `/api/v1/cert-manager/syncs/${destination}/${syncId}/import` + ); return data; }, @@ -157,7 +167,7 @@ export const useTriggerPkiSyncRemoveCertificates = () => { return useMutation({ mutationFn: async ({ syncId, destination }: TTriggerPkiSyncRemoveCertificatesDTO) => { const { data } = await apiRequest.post( - `/api/v1/pki/syncs/${destination}/${syncId}/remove-certificates` + `/api/v1/cert-manager/syncs/${destination}/${syncId}/remove-certificates` ); return data; @@ -209,9 +219,12 @@ export const useAddCertificatesToPkiSync = () => { pkiSyncId: string; certificateIds: string[]; }) => { - const { data } = await apiRequest.post(`/api/v1/pki/syncs/${pkiSyncId}/certificates`, { - certificateIds - }); + const { data } = await apiRequest.post( + `/api/v1/cert-manager/syncs/${pkiSyncId}/certificates`, + { + certificateIds + } + ); return data; }, @@ -231,9 +244,12 @@ export const useRemoveCertificatesFromPkiSync = () => { pkiSyncId: string; certificateIds: string[]; }) => { - const { data } = await apiRequest.delete(`/api/v1/pki/syncs/${pkiSyncId}/certificates`, { - data: { certificateIds } - }); + const { data } = await apiRequest.delete( + `/api/v1/cert-manager/syncs/${pkiSyncId}/certificates`, + { + data: { certificateIds } + } + ); return data; }, diff --git a/frontend/src/hooks/api/pkiSyncs/queries.tsx b/frontend/src/hooks/api/pkiSyncs/queries.tsx index 6e7aabc42..7000de99d 100644 --- a/frontend/src/hooks/api/pkiSyncs/queries.tsx +++ b/frontend/src/hooks/api/pkiSyncs/queries.tsx @@ -37,7 +37,9 @@ export const usePkiSyncOptions = ( return useQuery({ queryKey: pkiSyncKeys.options(), queryFn: async () => { - const { data } = await apiRequest.get("/api/v1/pki/syncs/options"); + const { data } = await apiRequest.get( + "/api/v1/cert-manager/syncs/options" + ); return data.pkiSyncOptions; }, @@ -58,7 +60,7 @@ export const fetchPkiSyncsByProjectId = async (projectId: string, certificateId? params.certificateId = certificateId; } - const { data } = await apiRequest.get("/api/v1/pki/syncs", { + const { data } = await apiRequest.get("/api/v1/cert-manager/syncs", { params }); @@ -110,7 +112,7 @@ export const useGetPkiSync = ( return useQuery({ queryKey: pkiSyncKeys.byId(syncId, projectId), queryFn: async () => { - const { data } = await apiRequest.get(`/api/v1/pki/syncs/${syncId}`, { + const { data } = await apiRequest.get(`/api/v1/cert-manager/syncs/${syncId}`, { params: { projectId } }); @@ -138,7 +140,7 @@ export const useListPkiSyncCertificates = ( return useQuery({ queryKey: pkiSyncKeys.certificates(syncId, { offset, limit }), queryFn: async () => { - const { data } = await apiRequest.get(`/api/v1/pki/syncs/${syncId}/certificates`, { + const { data } = await apiRequest.get(`/api/v1/cert-manager/syncs/${syncId}/certificates`, { params: { offset, limit } }); return { diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx index 51cc9edf5..b2cd5e696 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx @@ -44,10 +44,9 @@ const Page = () => { const params = useParams({ from: ROUTE_PATHS.CertManager.CertAuthDetailsByIDPage.id }); - const { caName } = params as { caName: string }; + const { caId } = params as { caId: string }; const { data } = useGetCa({ - caName, - projectId: currentProject?.id || "", + caId, type: CaType.INTERNAL }) as { data: TInternalCertificateAuthority }; @@ -66,7 +65,7 @@ const Page = () => { if (!currentProject?.slug) return; await deleteCa({ - caName, + id: data.id, projectId: currentProject.id, type: CaType.INTERNAL }); @@ -138,7 +137,7 @@ const Page = () => {
- +
diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaCrlsSection/CaCrlsTable.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaCrlsSection/CaCrlsTable.tsx index dfe87d027..77b96f3d6 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaCrlsSection/CaCrlsTable.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaCrlsSection/CaCrlsTable.tsx @@ -51,7 +51,7 @@ export const CaCrlsTable = ({ caId }: Props) => {
- {`${window.origin}/api/v1/pki/crl/${id}`} + {`${window.origin}/api/v1/cert-manager/crl/${id}`}
{/* {format(new Date(caCrlObj.thisUpdate), "yyyy-MM-dd")} */} diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaDetailsSection.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaDetailsSection.tsx index dd212eb40..b965d9600 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaDetailsSection.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaDetailsSection.tsx @@ -4,7 +4,7 @@ import { format } from "date-fns"; import { ProjectPermissionCan } from "@app/components/permissions"; import { Button, IconButton, Tooltip } from "@app/components/v2"; -import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context"; +import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context"; import { useTimedReset } from "@app/hooks"; import { CaStatus, CaType, InternalCaType, useGetCa } from "@app/hooks/api"; import { caStatusToNameMap, caTypeToNameMap } from "@app/hooks/api/ca/constants"; @@ -13,15 +13,14 @@ import { certKeyAlgorithmToNameMap } from "@app/hooks/api/certificates/constants import { UsePopUpState } from "@app/hooks/usePopUp"; type Props = { - caName: string; + caId: string; handlePopUpOpen: ( popUpName: keyof UsePopUpState<["ca", "renewCa", "installCaCert"]>, data?: object ) => void; }; -export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => { - const { currentProject } = useProject(); +export const CaDetailsSection = ({ caId, handlePopUpOpen }: Props) => { const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset({ initialState: "Copy ID to clipboard" }); @@ -30,8 +29,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => { }); const { data } = useGetCa({ - caName, - projectId: currentProject.id, + caId, type: CaType.INTERNAL }); @@ -53,7 +51,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => { onClick={(e) => { e.stopPropagation(); handlePopUpOpen("ca", { - name: ca.name + caId: ca.id }); }} > diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx index ad5e00acf..e0a84e5a9 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/route.tsx @@ -3,7 +3,7 @@ import { createFileRoute, linkOptions } from "@tanstack/react-router"; import { CertAuthDetailsByIDPage } from "./CertAuthDetailsByIDPage"; export const Route = createFileRoute( - "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName" + "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId" )({ component: CertAuthDetailsByIDPage, beforeLoad: ({ context, params }) => { @@ -21,7 +21,7 @@ export const Route = createFileRoute( }) }, { - label: params.caName + label: params.caId } ] }; diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx index f80e21212..f33b8c43f 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx @@ -9,8 +9,8 @@ import { Button, FormControl, Input, Select, SelectItem } from "@app/components/ import { useProject } from "@app/context"; import { CaStatus, - useGetCaById, useGetCaCsr, + useGetInternalCaById, useImportCaCertificate, useListWorkspaceCas, useSignIntermediate @@ -51,7 +51,7 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => { projectId: currentProject.id, status: CaStatus.ACTIVE }); - const { data: ca } = useGetCaById(caId); + const { data: ca } = useGetInternalCaById(caId); const { data: csr } = useGetCaCsr(caId); const { mutateAsync: signIntermediate } = useSignIntermediate(); @@ -83,18 +83,21 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => { const parentCaId = watch("parentCaId"); - const { data: parentCa } = useGetCaById(parentCaId); + const { data: parentCa } = useGetInternalCaById(parentCaId); useEffect(() => { - if (parentCa?.maxPathLength) { + if (parentCa?.configuration.maxPathLength) { setValue( "maxPathLength", - (parentCa.maxPathLength === -1 ? 3 : parentCa.maxPathLength - 1).toString() + (parentCa.configuration.maxPathLength === -1 + ? 3 + : parentCa.configuration.maxPathLength - 1 + ).toString() ); } - if (parentCa?.notAfter) { - const parentCaNotAfter = new Date(parentCa.notAfter); + if (parentCa?.configuration.notAfter) { + const parentCaNotAfter = new Date(parentCa.configuration.notAfter); const middleDate = getMiddleDate(new Date(), parentCaNotAfter); setValue("notAfter", format(middleDate, "yyyy-MM-dd")); } @@ -197,7 +200,7 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => { onValueChange={onChange} className="w-full" > - {generatePathLengthOpts(parentCa?.maxPathLength || 0).map((value) => ( + {generatePathLengthOpts(parentCa?.configuration.maxPathLength || 0).map((value) => ( {`${value}`} diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx index 53434b79d..a75ef4da3 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx @@ -80,8 +80,7 @@ const caTypes = [ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => { const { currentProject } = useProject(); const { data: ca } = useGetCa({ - caName: (popUp?.ca?.data as { name: string })?.name || "", - projectId: currentProject?.id || "", + caId: (popUp?.ca?.data as { caId: string })?.caId || "", type: CaType.INTERNAL }); @@ -180,8 +179,7 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => { if (ca) { // update await updateMutateAsync({ - caName: ca.name, - projectId: currentProject.id, + id: ca.id, name, type: CaType.INTERNAL, status, diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx index 918a844b1..7e121eec9 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx @@ -26,10 +26,10 @@ export const CaSection = () => { "caStatus" // enable / disable ] as const); - const onRemoveCaSubmit = async (caName: string) => { + const onRemoveCaSubmit = async (id: string) => { if (!currentProject?.slug) return; - await deleteCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL }); + await deleteCa({ id, projectId: currentProject.id, type: CaType.INTERNAL }); createNotification({ text: "Successfully deleted CA", @@ -39,10 +39,10 @@ export const CaSection = () => { handlePopUpClose("deleteCa"); }; - const onUpdateCaStatus = async ({ caName, status }: { caName: string; status: CaStatus }) => { + const onUpdateCaStatus = async ({ caId, status }: { caId: string; status: CaStatus }) => { if (!currentProject?.slug) return; - await updateCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL, status }); + await updateCa({ id: caId, type: CaType.INTERNAL, status }); createNotification({ text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`, @@ -85,9 +85,7 @@ export const CaSection = () => { subTitle="This action will delete other CAs and certificates below it in your CA hierarchy." onChange={(isOpen) => handlePopUpToggle("deleteCa", isOpen)} deleteKey="confirm" - onDeleteApproved={() => - onRemoveCaSubmit((popUp?.deleteCa?.data as { caName: string })?.caName) - } + onDeleteApproved={() => onRemoveCaSubmit((popUp?.deleteCa?.data as { caId: string })?.caId)} /> { onChange={(isOpen) => handlePopUpToggle("caStatus", isOpen)} deleteKey="confirm" onDeleteApproved={() => - onUpdateCaStatus(popUp?.caStatus?.data as { caName: string; status: CaStatus }) + onUpdateCaStatus(popUp?.caStatus?.data as { caId: string; status: CaStatus }) } />
diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaTable.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaTable.tsx index 2549cf327..27de9315a 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaTable.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaTable.tsx @@ -81,11 +81,11 @@ export const CaTable = ({ handlePopUpOpen }: Props) => { key={`ca-${ca.id}`} onClick={() => navigate({ - to: "/organizations/$orgId/projects/cert-management/$projectId/ca/$caName", + to: "/organizations/$orgId/projects/cert-management/$projectId/ca/$caId", params: { orgId: currentOrg.id, projectId: currentProject.id, - caName: ca.name + caId: ca.id } }) } @@ -180,7 +180,7 @@ export const CaTable = ({ handlePopUpOpen }: Props) => { onClick={(e) => { e.stopPropagation(); handlePopUpOpen("caStatus", { - caName: ca.name, + caId: ca.id, status: ca.status === CaStatus.ACTIVE ? CaStatus.DISABLED @@ -207,7 +207,7 @@ export const CaTable = ({ handlePopUpOpen }: Props) => { onClick={(e) => { e.stopPropagation(); handlePopUpOpen("deleteCa", { - caName: ca.name + caId: ca.id }); }} disabled={!isAllowed} diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaModal.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaModal.tsx index 1fb338a25..1555f994a 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaModal.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaModal.tsx @@ -131,8 +131,7 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { const { currentProject } = useProject(); const { data: ca, isLoading: isCaLoading } = useGetCa({ - caName: (popUp?.ca?.data as { name: string })?.name || "", - projectId: currentProject?.id || "", + caId: (popUp?.ca?.data as { caId: string })?.caId || "", type: (popUp?.ca?.data as { type: CaType })?.type || "" }); @@ -320,7 +319,7 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { if (ca) { await updateMutateAsync({ - caName: ca.name, + id: ca.id, projectId: currentProject.id, name, type, diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaSection.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaSection.tsx index 31894b855..460985ad5 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaSection.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaSection.tsx @@ -22,10 +22,10 @@ export const ExternalCaSection = () => { "caStatus" // enable / disable ] as const); - const onRemoveCaSubmit = async (caName: string, type: CaType) => { + const onRemoveCaSubmit = async (id: string, type: CaType) => { if (!currentProject?.id) return; - await deleteCa({ caName, type, projectId: currentProject.id }); + await deleteCa({ id, type, projectId: currentProject.id }); createNotification({ text: "Successfully deleted CA", @@ -36,17 +36,17 @@ export const ExternalCaSection = () => { }; const onUpdateCaStatus = async ({ - name, + caId, type, status }: { - name: string; + caId: string; type: CaType; status: CaStatus; }) => { if (!currentProject?.slug) return; - await updateCa({ caName: name, type, status, projectId: currentProject.id }); + await updateCa({ id: caId, type, status }); createNotification({ text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`, @@ -88,7 +88,7 @@ export const ExternalCaSection = () => { deleteKey="confirm" onDeleteApproved={() => onRemoveCaSubmit( - (popUp?.deleteCa?.data as { name: string })?.name, + (popUp?.deleteCa?.data as { caId: string })?.caId, (popUp?.deleteCa?.data as { type: CaType })?.type ) } @@ -110,7 +110,7 @@ export const ExternalCaSection = () => { deleteKey="confirm" onDeleteApproved={() => onUpdateCaStatus( - popUp?.caStatus?.data as { name: string; type: CaType; status: CaStatus } + popUp?.caStatus?.data as { caId: string; type: CaType; status: CaStatus } ) } /> diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaTable.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaTable.tsx index 379a091c7..017bd4506 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaTable.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaTable.tsx @@ -35,6 +35,7 @@ type Props = { handlePopUpOpen: ( popUpName: keyof UsePopUpState<["ca", "deleteCa", "caStatus"]>, data?: { + caId?: string; name?: string; type?: CaType; status?: CaStatus; @@ -70,6 +71,7 @@ export const ExternalCaTable = ({ handlePopUpOpen }: Props) => { key={`ca-${ca.id}`} onClick={() => { handlePopUpOpen("ca", { + caId: ca.id, name: ca.name, type: ca.type }); @@ -104,6 +106,7 @@ export const ExternalCaTable = ({ handlePopUpOpen }: Props) => { onClick={(e) => { e.stopPropagation(); handlePopUpOpen("ca", { + caId: ca.id, name: ca.name, type: ca.type }); @@ -129,7 +132,7 @@ export const ExternalCaTable = ({ handlePopUpOpen }: Props) => { onClick={(e) => { e.stopPropagation(); handlePopUpOpen("caStatus", { - name: ca.name, + caId: ca.id, type: ca.type, status: ca.status === CaStatus.ACTIVE @@ -157,7 +160,7 @@ export const ExternalCaTable = ({ handlePopUpOpen }: Props) => { onClick={(e) => { e.stopPropagation(); handlePopUpOpen("deleteCa", { - name: ca.name, + caId: ca.id, type: ca.type }); }} diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateRevocationModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateRevocationModal.tsx index 14e8d100a..34b8a80cc 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateRevocationModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateRevocationModal.tsx @@ -50,11 +50,11 @@ export const CertificateRevocationModal = ({ popUp, handlePopUpToggle }: Props) const onFormSubmit = async ({ revocationReason }: FormData) => { if (!currentProject?.slug) return; - const { serialNumber } = popUp.revokeCertificate.data as { serialNumber: string }; + const { certificateId } = popUp.revokeCertificate.data as { certificateId: string }; await revokeCertificate({ projectId: currentProject.id, - serialNumber, + id: certificateId, revocationReason }); diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplateModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplateModal.tsx index 0ba3721e3..c20678724 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplateModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateTemplateModal.tsx @@ -26,8 +26,8 @@ import { useProject } from "@app/context"; import { CaStatus, useCreateCertTemplate, - useGetCaById, useGetCertTemplate, + useGetInternalCaById, useListWorkspaceCas, useListWorkspacePkiCollections, useUpdateCertTemplate @@ -84,7 +84,7 @@ type Props = { export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Props) => { const { currentProject } = useProject(); - const { data: ca } = useGetCaById(caId); + const { data: ca } = useGetInternalCaById(caId); const { data: certTemplate } = useGetCertTemplate( (popUp?.certificateTemplate?.data as { id: string })?.id || "" diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx index e151df542..36c4b4f71 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx @@ -39,11 +39,11 @@ export const CertificatesSection = () => { "managePkiSyncs" ] as const); - const onRemoveCertificateSubmit = async (serialNumber: string) => { + const onRemoveCertificateSubmit = async (id: string) => { if (!currentProject?.slug) return; await deleteCert({ - serialNumber, + id, projectId: currentProject.id }); @@ -150,7 +150,7 @@ export const CertificatesSection = () => { deleteKey="confirm" onDeleteApproved={() => onRemoveCertificateSubmit( - (popUp?.deleteCertificate?.data as { serialNumber: string })?.serialNumber + (popUp?.deleteCertificate?.data as { certificateId: string })?.certificateId ) } /> diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx index 39b43129c..e6d10bcd6 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx @@ -501,7 +501,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => { )} onClick={async () => handlePopUpOpen("revokeCertificate", { - serialNumber: certificate.serialNumber + certificateId: certificate.id }) } disabled={!isAllowed} @@ -524,7 +524,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => { )} onClick={async () => handlePopUpOpen("deleteCertificate", { - serialNumber: certificate.serialNumber, + certificateId: certificate.id, commonName: certificate.commonName }) } diff --git a/frontend/src/pages/cert-manager/PkiSubscriberDetailsByIDPage/components/PkiSubscriberCertificatesTable.tsx b/frontend/src/pages/cert-manager/PkiSubscriberDetailsByIDPage/components/PkiSubscriberCertificatesTable.tsx index 129af29d3..5540ab4d6 100644 --- a/frontend/src/pages/cert-manager/PkiSubscriberDetailsByIDPage/components/PkiSubscriberCertificatesTable.tsx +++ b/frontend/src/pages/cert-manager/PkiSubscriberDetailsByIDPage/components/PkiSubscriberCertificatesTable.tsx @@ -171,7 +171,7 @@ export const PkiSubscriberCertificatesTable = ({ subscriberName, handlePopUpOpen onClick={() => handlePopUpOpen && handlePopUpOpen("revokeCertificate", { - serialNumber: certificate.serialNumber + certificateId: certificate.id }) } disabled={!isAllowed} diff --git a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/ProfileRow.tsx b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/ProfileRow.tsx index c2ec7b688..f8fc8090b 100644 --- a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/ProfileRow.tsx +++ b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/ProfileRow.tsx @@ -29,7 +29,7 @@ import { ProjectPermissionSub } from "@app/context/ProjectPermissionContext/types"; import { usePopUp, useToggle } from "@app/hooks"; -import { useGetCaById } from "@app/hooks/api/ca/queries"; +import { useGetInternalCaById } from "@app/hooks/api/ca/queries"; import { IssuerType, TCertificateProfile } from "@app/hooks/api/certificateProfiles"; import { useGetCertificateTemplateV2ById } from "@app/hooks/api/certificateTemplates/queries"; import { CertificateIssuanceModal } from "@app/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal"; @@ -49,7 +49,7 @@ export const ProfileRow = ({ }: Props) => { const { permission } = useProjectPermission(); - const { data: caData } = useGetCaById(profile.caId ?? ""); + const { data: caData } = useGetInternalCaById(profile.caId ?? ""); const { popUp, handlePopUpToggle } = usePopUp(["issueCertificate"] as const); @@ -123,7 +123,9 @@ export const ProfileRow = ({ {profile.issuerType === IssuerType.SELF_SIGNED ? "Self-signed" - : caData?.friendlyName || caData?.commonName || profile.caId} + : caData?.configuration.friendlyName || + caData?.configuration.commonName || + profile.caId} diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts index f2954f03c..ca413ef21 100644 --- a/frontend/src/routeTree.gen.ts +++ b/frontend/src/routeTree.gen.ts @@ -1515,8 +1515,8 @@ const certManagerPkiSyncDetailsByIDPageRouteRoute = const certManagerCertAuthDetailsByIDPageRouteRoute = certManagerCertAuthDetailsByIDPageRouteImport.update({ - id: '/ca/$caName', - path: '/ca/$caName', + id: '/ca/$caId', + path: '/ca/$caId', getParentRoute: () => certManagerLayoutRoute, } as any) @@ -3182,10 +3182,10 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof secretScanningSecretScanningDataSourcesPageRouteImport parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationsOrgIdProjectsSecretScanningProjectIdSecretScanningLayoutDataSourcesImport } - '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName': { - id: '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName' - path: '/ca/$caName' - fullPath: '/organizations/$orgId/projects/cert-management/$projectId/ca/$caName' + '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId': { + id: '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId' + path: '/ca/$caId' + fullPath: '/organizations/$orgId/projects/cert-management/$projectId/ca/$caId' preLoaderRoute: typeof certManagerCertAuthDetailsByIDPageRouteImport parentRoute: typeof certManagerLayoutImport } @@ -5199,7 +5199,7 @@ export interface FileRoutesByFullPath { '/organizations/$orgId/projects/pam/$projectId/sessions/': typeof pamPamSessionsPageRouteRoute '/organizations/$orgId/projects/secret-management/$projectId/integrations/': typeof secretManagerIntegrationsListPageRouteRoute '/organizations/$orgId/projects/secret-scanning/$projectId/data-sources/': typeof secretScanningSecretScanningDataSourcesPageRouteRoute - '/organizations/$orgId/projects/cert-management/$projectId/ca/$caName': typeof certManagerCertAuthDetailsByIDPageRouteRoute + '/organizations/$orgId/projects/cert-management/$projectId/ca/$caId': typeof certManagerCertAuthDetailsByIDPageRouteRoute '/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId': typeof certManagerPkiSyncDetailsByIDPageRouteRoute '/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName': typeof certManagerPkiSubscriberDetailsByIDPageRouteRoute '/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId': typeof pamPamSessionsByIDPageRouteRoute @@ -5429,7 +5429,7 @@ export interface FileRoutesByTo { '/organizations/$orgId/projects/pam/$projectId/sessions': typeof pamPamSessionsPageRouteRoute '/organizations/$orgId/projects/secret-management/$projectId/integrations': typeof secretManagerIntegrationsListPageRouteRoute '/organizations/$orgId/projects/secret-scanning/$projectId/data-sources': typeof secretScanningSecretScanningDataSourcesPageRouteRoute - '/organizations/$orgId/projects/cert-management/$projectId/ca/$caName': typeof certManagerCertAuthDetailsByIDPageRouteRoute + '/organizations/$orgId/projects/cert-management/$projectId/ca/$caId': typeof certManagerCertAuthDetailsByIDPageRouteRoute '/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId': typeof certManagerPkiSyncDetailsByIDPageRouteRoute '/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName': typeof certManagerPkiSubscriberDetailsByIDPageRouteRoute '/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId': typeof pamPamSessionsByIDPageRouteRoute @@ -5682,7 +5682,7 @@ export interface FileRoutesById { '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/': typeof pamPamSessionsPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/': typeof secretManagerIntegrationsListPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-scanning/$projectId/_secret-scanning-layout/data-sources/': typeof secretScanningSecretScanningDataSourcesPageRouteRoute - '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName': typeof certManagerCertAuthDetailsByIDPageRouteRoute + '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId': typeof certManagerCertAuthDetailsByIDPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/integrations/$syncId': typeof certManagerPkiSyncDetailsByIDPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers/$subscriberName': typeof certManagerPkiSubscriberDetailsByIDPageRouteRoute '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/$sessionId': typeof pamPamSessionsByIDPageRouteRoute @@ -5927,7 +5927,7 @@ export interface FileRouteTypes { | '/organizations/$orgId/projects/pam/$projectId/sessions/' | '/organizations/$orgId/projects/secret-management/$projectId/integrations/' | '/organizations/$orgId/projects/secret-scanning/$projectId/data-sources/' - | '/organizations/$orgId/projects/cert-management/$projectId/ca/$caName' + | '/organizations/$orgId/projects/cert-management/$projectId/ca/$caId' | '/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId' | '/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName' | '/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId' @@ -6156,7 +6156,7 @@ export interface FileRouteTypes { | '/organizations/$orgId/projects/pam/$projectId/sessions' | '/organizations/$orgId/projects/secret-management/$projectId/integrations' | '/organizations/$orgId/projects/secret-scanning/$projectId/data-sources' - | '/organizations/$orgId/projects/cert-management/$projectId/ca/$caName' + | '/organizations/$orgId/projects/cert-management/$projectId/ca/$caId' | '/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId' | '/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName' | '/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId' @@ -6407,7 +6407,7 @@ export interface FileRouteTypes { | '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/' | '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/' | '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-scanning/$projectId/_secret-scanning-layout/data-sources/' - | '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName' + | '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId' | '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/integrations/$syncId' | '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers/$subscriberName' | '/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/$sessionId' @@ -7030,7 +7030,7 @@ export const routeTree = rootRoute "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/certificate-templates", "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/integrations", "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers", - "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName", + "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId", "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/groups/$groupId", "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/identities/$identityId", "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/members/$membershipId", @@ -7415,7 +7415,7 @@ export const routeTree = rootRoute "filePath": "secret-scanning/SecretScanningDataSourcesPage/route.tsx", "parent": "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-scanning/$projectId/_secret-scanning-layout/data-sources" }, - "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName": { + "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId": { "filePath": "cert-manager/CertAuthDetailsByIDPage/route.tsx", "parent": "/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout" }, diff --git a/frontend/src/routes.ts b/frontend/src/routes.ts index 265c64649..b0b52c4d3 100644 --- a/frontend/src/routes.ts +++ b/frontend/src/routes.ts @@ -282,7 +282,7 @@ const certManagerRoutes = route("/organizations/$orgId/projects/cert-management/ route("/certificate-templates", [index("cert-manager/PkiTemplateListPage/route.tsx")]), route("/certificate-authorities", "cert-manager/CertificateAuthoritiesPage/route.tsx"), route("/alerting", "cert-manager/AlertingPage/route.tsx"), - route("/ca/$caName", "cert-manager/CertAuthDetailsByIDPage/route.tsx"), + route("/ca/$caId", "cert-manager/CertAuthDetailsByIDPage/route.tsx"), route("/pki-collections/$collectionId", "cert-manager/PkiCollectionDetailsByIDPage/routes.tsx"), route("/integrations", [ index("cert-manager/IntegrationsListPage/route.tsx"), From 1531048d2542ec6112e994b8a925fcf9cacb9812 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Wed, 26 Nov 2025 04:10:05 +0800 Subject: [PATCH 2/8] mics: updated docs --- .../server/routes/v1/certificate-router.ts | 20 ++++----- .../certificate-authorities/acme/create.mdx | 2 +- .../certificate-authorities/acme/delete.mdx | 2 +- .../certificate-authorities/acme/list.mdx | 2 +- .../certificate-authorities/acme/read.mdx | 2 +- .../certificate-authorities/acme/update.mdx | 2 +- .../certificate-authorities/cert.mdx | 4 -- .../certificate-authorities/create.mdx | 8 ---- .../endpoints/certificate-authorities/crl.mdx | 4 -- .../endpoints/certificate-authorities/csr.mdx | 4 -- .../certificate-authorities/delete.mdx | 8 ---- .../certificate-authorities/import-cert.mdx | 4 -- .../certificate-authorities/internal/cert.mdx | 4 ++ .../internal/create.mdx | 2 +- .../certificate-authorities/internal/crl.mdx | 4 ++ .../certificate-authorities/internal/csr.mdx | 4 ++ .../internal/delete.mdx | 2 +- .../internal/import-cert.mdx | 4 ++ .../internal/list-ca-certs.mdx | 4 ++ .../certificate-authorities/internal/list.mdx | 2 +- .../certificate-authorities/internal/read.mdx | 2 +- .../internal/renew.mdx | 4 ++ .../internal/sign-intermediate.mdx | 4 ++ .../internal/update.mdx | 2 +- .../certificate-authorities/list-ca-certs.mdx | 4 -- .../certificate-authorities/list.mdx | 8 ---- .../certificate-authorities/read.mdx | 8 ---- .../certificate-authorities/renew.mdx | 4 -- .../sign-intermediate.mdx | 4 -- .../certificate-authorities/update.mdx | 8 ---- .../endpoints/certificate-profiles/create.mdx | 2 +- .../endpoints/certificate-profiles/delete.mdx | 2 +- .../certificate-profiles/get-by-id.mdx | 2 +- .../certificate-profiles/get-by-slug.mdx | 2 +- .../get-latest-active-bundle.mdx | 2 +- .../list-certificates.mdx | 2 +- .../endpoints/certificate-profiles/list.mdx | 2 +- .../endpoints/certificate-profiles/update.mdx | 2 +- .../endpoints/certificate-syncs/list.mdx | 2 +- .../endpoints/certificate-syncs/options.mdx | 2 +- .../certificate-templates-v2/create.mdx | 4 -- .../certificate-templates-v2/delete.mdx | 4 -- .../certificate-templates-v2/get-by-id.mdx | 4 -- .../certificate-templates-v2/list.mdx | 4 -- .../certificate-templates-v2/update.mdx | 4 -- .../certificate-templates/create.mdx | 4 ++ .../certificate-templates/delete.mdx | 4 ++ .../certificate-templates/get-by-id.mdx | 4 ++ .../endpoints/certificate-templates/list.mdx | 4 ++ .../certificate-templates/update.mdx | 4 ++ .../endpoints/certificates/bundle.mdx | 2 +- .../endpoints/certificates/cert-body.mdx | 2 +- .../endpoints/certificates/delete.mdx | 2 +- .../certificates/issue-certificate.mdx | 2 +- .../endpoints/certificates/private-key.mdx | 2 +- .../endpoints/certificates/read.mdx | 2 +- .../endpoints/certificates/renew.mdx | 2 +- .../endpoints/certificates/revoke.mdx | 2 +- .../certificates/sign-certificate.mdx | 2 +- .../endpoints/certificates/update-config.mdx | 2 +- .../endpoints/pki/syncs/add-certificates.mdx | 2 +- .../syncs/aws-certificate-manager/create.mdx | 2 +- .../syncs/aws-certificate-manager/delete.mdx | 2 +- .../aws-certificate-manager/get-by-id.mdx | 2 +- .../syncs/aws-certificate-manager/list.mdx | 2 +- .../remove-certificates.mdx | 2 +- .../sync-certificates.mdx | 2 +- .../syncs/aws-certificate-manager/update.mdx | 2 +- .../pki/syncs/aws-secrets-manager/create.mdx | 2 +- .../pki/syncs/aws-secrets-manager/delete.mdx | 2 +- .../syncs/aws-secrets-manager/get-by-id.mdx | 2 +- .../pki/syncs/aws-secrets-manager/list.mdx | 2 +- .../remove-certificates.mdx | 2 +- .../aws-secrets-manager/sync-certificates.mdx | 2 +- .../pki/syncs/aws-secrets-manager/update.mdx | 2 +- .../pki/syncs/azure-key-vault/create.mdx | 2 +- .../pki/syncs/azure-key-vault/delete.mdx | 2 +- .../pki/syncs/azure-key-vault/get-by-id.mdx | 2 +- .../pki/syncs/azure-key-vault/list.mdx | 2 +- .../azure-key-vault/remove-certificates.mdx | 2 +- .../azure-key-vault/sync-certificates.mdx | 2 +- .../pki/syncs/azure-key-vault/update.mdx | 2 +- .../endpoints/pki/syncs/chef/create.mdx | 2 +- .../endpoints/pki/syncs/chef/delete.mdx | 2 +- .../endpoints/pki/syncs/chef/get-by-id.mdx | 2 +- .../endpoints/pki/syncs/chef/list.mdx | 2 +- .../pki/syncs/chef/remove-certificates.mdx | 2 +- .../pki/syncs/chef/sync-certificates.mdx | 2 +- .../endpoints/pki/syncs/chef/update.mdx | 2 +- .../endpoints/pki/syncs/get-by-id.mdx | 2 +- .../endpoints/pki/syncs/list-certificates.mdx | 2 +- .../endpoints/pki/syncs/list.mdx | 2 +- .../endpoints/pki/syncs/options.mdx | 2 +- .../pki/syncs/remove-certificates.mdx | 2 +- docs/docs.json | 45 ++++++------------- .../documentation/platform/pki/ca/acme-ca.mdx | 2 +- .../platform/pki/ca/private-ca.mdx | 12 ++--- .../aws-certificate-manager.mdx | 2 +- .../certificate-syncs/aws-secrets-manager.mdx | 4 +- .../pki/certificate-syncs/azure-key-vault.mdx | 2 +- .../platform/pki/certificate-syncs/chef.mdx | 4 +- .../platform/pki/certificates.mdx | 6 +-- .../pki/certificates/certificates.mdx | 4 +- .../platform/pki/enrollment-methods/acme.mdx | 2 +- .../platform/pki/enrollment-methods/api.mdx | 2 +- .../pki/integration-guides/apache-certbot.mdx | 4 +- .../pki/integration-guides/jboss-certbot.mdx | 4 +- .../pki/integration-guides/nginx-certbot.mdx | 4 +- .../pki/integration-guides/tomcat-certbot.mdx | 4 +- .../windows-server-acme.mdx | 14 +++--- 110 files changed, 171 insertions(+), 228 deletions(-) delete mode 100644 docs/api-reference/endpoints/certificate-authorities/cert.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/create.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/crl.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/csr.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/delete.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/import-cert.mdx create mode 100644 docs/api-reference/endpoints/certificate-authorities/internal/cert.mdx create mode 100644 docs/api-reference/endpoints/certificate-authorities/internal/crl.mdx create mode 100644 docs/api-reference/endpoints/certificate-authorities/internal/csr.mdx create mode 100644 docs/api-reference/endpoints/certificate-authorities/internal/import-cert.mdx create mode 100644 docs/api-reference/endpoints/certificate-authorities/internal/list-ca-certs.mdx create mode 100644 docs/api-reference/endpoints/certificate-authorities/internal/renew.mdx create mode 100644 docs/api-reference/endpoints/certificate-authorities/internal/sign-intermediate.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/list-ca-certs.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/list.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/read.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/renew.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/sign-intermediate.mdx delete mode 100644 docs/api-reference/endpoints/certificate-authorities/update.mdx delete mode 100644 docs/api-reference/endpoints/certificate-templates-v2/create.mdx delete mode 100644 docs/api-reference/endpoints/certificate-templates-v2/delete.mdx delete mode 100644 docs/api-reference/endpoints/certificate-templates-v2/get-by-id.mdx delete mode 100644 docs/api-reference/endpoints/certificate-templates-v2/list.mdx delete mode 100644 docs/api-reference/endpoints/certificate-templates-v2/update.mdx create mode 100644 docs/api-reference/endpoints/certificate-templates/create.mdx create mode 100644 docs/api-reference/endpoints/certificate-templates/delete.mdx create mode 100644 docs/api-reference/endpoints/certificate-templates/get-by-id.mdx create mode 100644 docs/api-reference/endpoints/certificate-templates/list.mdx create mode 100644 docs/api-reference/endpoints/certificate-templates/update.mdx diff --git a/backend/src/server/routes/v1/certificate-router.ts b/backend/src/server/routes/v1/certificate-router.ts index c2e322d69..a4af7fd92 100644 --- a/backend/src/server/routes/v1/certificate-router.ts +++ b/backend/src/server/routes/v1/certificate-router.ts @@ -360,7 +360,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { server.route({ method: "POST", - url: "/:certificateId/renew", + url: "/:id/renew", config: { rateLimit: writeLimit }, @@ -368,7 +368,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { hide: false, tags: [ApiDocsTags.PkiCertificates], params: z.object({ - certificateId: z.string().uuid() + id: z.string().uuid() }), body: z .object({ @@ -393,7 +393,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, actorOrgId: req.permission.orgId, - certificateId: req.params.certificateId, + certificateId: req.params.id, removeRootsFromChain: req.body?.removeRootsFromChain }); @@ -403,7 +403,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { event: { type: EventType.RENEW_CERTIFICATE, metadata: { - originalCertificateId: req.params.certificateId, + originalCertificateId: req.params.id, newCertificateId: data.certificateId, profileName: data.profileName, commonName: data.commonName @@ -417,7 +417,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { server.route({ method: "PATCH", - url: "/:certificateId/config", + url: "/:id/config", config: { rateLimit: writeLimit }, @@ -425,7 +425,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { hide: false, tags: [ApiDocsTags.PkiCertificates], params: z.object({ - certificateId: z.string().uuid() + id: z.string().uuid() }), body: z .object({ @@ -450,7 +450,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, actorOrgId: req.permission.orgId, - certificateId: req.params.certificateId + certificateId: req.params.id }); await server.services.auditLog.createAuditLog({ @@ -459,7 +459,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { event: { type: EventType.DISABLE_CERTIFICATE_RENEWAL_CONFIG, metadata: { - certificateId: req.params.certificateId, + certificateId: req.params.id, commonName: data.commonName } } @@ -476,7 +476,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, actorOrgId: req.permission.orgId, - certificateId: req.params.certificateId, + certificateId: req.params.id, renewBeforeDays: req.body.renewBeforeDays }); @@ -486,7 +486,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => { event: { type: EventType.UPDATE_CERTIFICATE_RENEWAL_CONFIG, metadata: { - certificateId: req.params.certificateId, + certificateId: req.params.id, renewBeforeDays: req.body.renewBeforeDays.toString(), commonName: data.commonName } diff --git a/docs/api-reference/endpoints/certificate-authorities/acme/create.mdx b/docs/api-reference/endpoints/certificate-authorities/acme/create.mdx index 9cc42ed7f..ef98a7fa1 100644 --- a/docs/api-reference/endpoints/certificate-authorities/acme/create.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/acme/create.mdx @@ -1,4 +1,4 @@ --- title: "Create" -openapi: "POST /api/v1/pki/ca/acme" +openapi: "POST /api/v1/cert-manager/ca/acme" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/acme/delete.mdx b/docs/api-reference/endpoints/certificate-authorities/acme/delete.mdx index 9decc3b6e..eac21ef03 100644 --- a/docs/api-reference/endpoints/certificate-authorities/acme/delete.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/acme/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete" -openapi: "DELETE /api/v1/pki/ca/acme/{caName}" +openapi: "DELETE /api/v1/cert-manager/ca/acme/{id}" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/acme/list.mdx b/docs/api-reference/endpoints/certificate-authorities/acme/list.mdx index 35bd70727..569efb9af 100644 --- a/docs/api-reference/endpoints/certificate-authorities/acme/list.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/acme/list.mdx @@ -1,4 +1,4 @@ --- title: "List" -openapi: "GET /api/v1/pki/ca/acme" +openapi: "GET /api/v1/cert-manager/ca/acme" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/acme/read.mdx b/docs/api-reference/endpoints/certificate-authorities/acme/read.mdx index a80e31f9a..55f022a3c 100644 --- a/docs/api-reference/endpoints/certificate-authorities/acme/read.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/acme/read.mdx @@ -1,4 +1,4 @@ --- title: "Read" -openapi: "GET /api/v1/pki/ca/acme/{caName}" +openapi: "GET /api/v1/cert-manager/ca/acme/{id}" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/acme/update.mdx b/docs/api-reference/endpoints/certificate-authorities/acme/update.mdx index 69f758771..f9be04fda 100644 --- a/docs/api-reference/endpoints/certificate-authorities/acme/update.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/acme/update.mdx @@ -1,4 +1,4 @@ --- title: "Update" -openapi: "PATCH /api/v1/pki/ca/acme/{caName}" +openapi: "PATCH /api/v1/cert-manager/ca/acme/{id}" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/cert.mdx b/docs/api-reference/endpoints/certificate-authorities/cert.mdx deleted file mode 100644 index 3706e0b11..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/cert.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Retrieve certificate / chain" -openapi: "GET /api/v1/pki/ca/{caId}/certificate" ---- diff --git a/docs/api-reference/endpoints/certificate-authorities/create.mdx b/docs/api-reference/endpoints/certificate-authorities/create.mdx deleted file mode 100644 index 276015228..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/create.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Create (Deprecated)" -openapi: "POST /api/v1/pki/ca" ---- - - - This endpoint is deprecated. Please use the internal CA endpoint [here](/api-reference/endpoints/certificate-authorities/internal/create). - \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-authorities/crl.mdx b/docs/api-reference/endpoints/certificate-authorities/crl.mdx deleted file mode 100644 index 428c3377e..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/crl.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "List CRLs" -openapi: "GET /api/v1/pki/ca/{caId}/crls" ---- diff --git a/docs/api-reference/endpoints/certificate-authorities/csr.mdx b/docs/api-reference/endpoints/certificate-authorities/csr.mdx deleted file mode 100644 index 2477a629e..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/csr.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Get CSR" -openapi: "GET /api/v1/pki/ca/{caId}/csr" ---- diff --git a/docs/api-reference/endpoints/certificate-authorities/delete.mdx b/docs/api-reference/endpoints/certificate-authorities/delete.mdx deleted file mode 100644 index c4ded070d..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/delete.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Delete (Deprecated)" -openapi: "DELETE /api/v1/pki/ca/{caId}" ---- - - - This endpoint is deprecated. Please use the internal CA endpoint [here](/api-reference/endpoints/certificate-authorities/internal/delete). - \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-authorities/import-cert.mdx b/docs/api-reference/endpoints/certificate-authorities/import-cert.mdx deleted file mode 100644 index 7f0e40f95..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/import-cert.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Import certificate" -openapi: "POST /api/v1/pki/ca/{caId}/import-certificate" ---- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/cert.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/cert.mdx new file mode 100644 index 000000000..476746c55 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-authorities/internal/cert.mdx @@ -0,0 +1,4 @@ +--- +title: "Retrieve certificate / chain" +openapi: "GET /api/v1/cert-manager/ca/internal/{caId}/certificate" +--- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/create.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/create.mdx index babc144f2..9f1567c61 100644 --- a/docs/api-reference/endpoints/certificate-authorities/internal/create.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/internal/create.mdx @@ -1,4 +1,4 @@ --- title: "Create" -openapi: "POST /api/v1/pki/ca/internal" +openapi: "POST /api/v1/cert-manager/ca/internal" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/crl.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/crl.mdx new file mode 100644 index 000000000..3a9bb4c62 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-authorities/internal/crl.mdx @@ -0,0 +1,4 @@ +--- +title: "List CRLs" +openapi: "GET /api/v1/cert-manager/ca/internal/{caId}/crls" +--- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/csr.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/csr.mdx new file mode 100644 index 000000000..4a2e72505 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-authorities/internal/csr.mdx @@ -0,0 +1,4 @@ +--- +title: "Get CSR" +openapi: "GET /api/v1/cert-manager/ca/internal/{caId}/csr" +--- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/delete.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/delete.mdx index b1b7f20a7..7e38781ec 100644 --- a/docs/api-reference/endpoints/certificate-authorities/internal/delete.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/internal/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete" -openapi: "DELETE /api/v1/pki/ca/internal/{caName}" +openapi: "DELETE /api/v1/cert-manager/ca/internal/{id}" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/import-cert.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/import-cert.mdx new file mode 100644 index 000000000..ba4aeb2d0 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-authorities/internal/import-cert.mdx @@ -0,0 +1,4 @@ +--- +title: "Import certificate" +openapi: "POST /api/v1/cert-manager/ca/internal/{caId}/import-certificate" +--- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/list-ca-certs.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/list-ca-certs.mdx new file mode 100644 index 000000000..b29444b73 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-authorities/internal/list-ca-certs.mdx @@ -0,0 +1,4 @@ +--- +title: "List CA certificates" +openapi: "GET /api/v1/cert-manager/ca/internal/{caId}/ca-certificates" +--- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/list.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/list.mdx index 43f2b7108..bfced601b 100644 --- a/docs/api-reference/endpoints/certificate-authorities/internal/list.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/internal/list.mdx @@ -1,4 +1,4 @@ --- title: "List" -openapi: "GET /api/v1/pki/ca/internal" +openapi: "GET /api/v1/cert-manager/ca/internal" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/read.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/read.mdx index d269564cf..85f9582df 100644 --- a/docs/api-reference/endpoints/certificate-authorities/internal/read.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/internal/read.mdx @@ -1,4 +1,4 @@ --- title: "Read" -openapi: "GET /api/v1/pki/ca/internal/{caName}" +openapi: "GET /api/v1/cert-manager/ca/internal/{id}" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/renew.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/renew.mdx new file mode 100644 index 000000000..d32963d3f --- /dev/null +++ b/docs/api-reference/endpoints/certificate-authorities/internal/renew.mdx @@ -0,0 +1,4 @@ +--- +title: "Renew" +openapi: "POST /api/v1/cert-manager/ca/internal/{caId}/renew" +--- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/sign-intermediate.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/sign-intermediate.mdx new file mode 100644 index 000000000..e6d185f95 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-authorities/internal/sign-intermediate.mdx @@ -0,0 +1,4 @@ +--- +title: "Sign intermediate certificate" +openapi: "POST /api/v1/cert-manager/ca/internal/{caId}/sign-intermediate" +--- diff --git a/docs/api-reference/endpoints/certificate-authorities/internal/update.mdx b/docs/api-reference/endpoints/certificate-authorities/internal/update.mdx index b01899884..770704e4c 100644 --- a/docs/api-reference/endpoints/certificate-authorities/internal/update.mdx +++ b/docs/api-reference/endpoints/certificate-authorities/internal/update.mdx @@ -1,4 +1,4 @@ --- title: "Update" -openapi: "PATCH /api/v1/pki/ca/internal/{caName}" +openapi: "PATCH /api/v1/cert-manager/ca/internal/{id}" --- diff --git a/docs/api-reference/endpoints/certificate-authorities/list-ca-certs.mdx b/docs/api-reference/endpoints/certificate-authorities/list-ca-certs.mdx deleted file mode 100644 index ce253807c..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/list-ca-certs.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "List CA certificates" -openapi: "GET /api/v1/pki/ca/{caId}/ca-certificates" ---- diff --git a/docs/api-reference/endpoints/certificate-authorities/list.mdx b/docs/api-reference/endpoints/certificate-authorities/list.mdx deleted file mode 100644 index 81dd64af6..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/list.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "List (Deprecated)" -openapi: "GET /api/v2/workspace/{slug}/cas" ---- - - - This endpoint is deprecated. Please use the internal CA endpoint [here](/api-reference/endpoints/certificate-authorities/internal/list). - \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-authorities/read.mdx b/docs/api-reference/endpoints/certificate-authorities/read.mdx deleted file mode 100644 index bca5121bd..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/read.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Retrieve (Deprecated)" -openapi: "GET /api/v1/pki/ca/{caId}" ---- - - - This endpoint is deprecated. Please use the internal CA endpoint [here](/api-reference/endpoints/certificate-authorities/internal/read). - \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-authorities/renew.mdx b/docs/api-reference/endpoints/certificate-authorities/renew.mdx deleted file mode 100644 index 901811f2d..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/renew.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Renew" -openapi: "POST /api/v1/pki/ca/{caId}/renew" ---- diff --git a/docs/api-reference/endpoints/certificate-authorities/sign-intermediate.mdx b/docs/api-reference/endpoints/certificate-authorities/sign-intermediate.mdx deleted file mode 100644 index 310bbea26..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/sign-intermediate.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Sign intermediate certificate" -openapi: "POST /api/v1/pki/ca/{caId}/sign-intermediate" ---- diff --git a/docs/api-reference/endpoints/certificate-authorities/update.mdx b/docs/api-reference/endpoints/certificate-authorities/update.mdx deleted file mode 100644 index 0cd88ebf6..000000000 --- a/docs/api-reference/endpoints/certificate-authorities/update.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Update (Deprecated)" -openapi: "PATCH /api/v1/pki/ca/{caId}" ---- - - - This endpoint is deprecated. Please use the internal CA endpoint [here](/api-reference/endpoints/certificate-authorities/internal/update). - \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-profiles/create.mdx b/docs/api-reference/endpoints/certificate-profiles/create.mdx index e24e42207..c6ed780e7 100644 --- a/docs/api-reference/endpoints/certificate-profiles/create.mdx +++ b/docs/api-reference/endpoints/certificate-profiles/create.mdx @@ -1,4 +1,4 @@ --- title: "Create" -openapi: "POST /api/v1/pki/certificate-profiles" +openapi: "POST /api/v1/cert-manager/certificate-profiles" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-profiles/delete.mdx b/docs/api-reference/endpoints/certificate-profiles/delete.mdx index a1762640a..966fce508 100644 --- a/docs/api-reference/endpoints/certificate-profiles/delete.mdx +++ b/docs/api-reference/endpoints/certificate-profiles/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete" -openapi: "DELETE /api/v1/pki/certificate-profiles/{id}" +openapi: "DELETE /api/v1/cert-manager/certificate-profiles/{id}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-profiles/get-by-id.mdx b/docs/api-reference/endpoints/certificate-profiles/get-by-id.mdx index 38e0c20f8..c3f73e6ac 100644 --- a/docs/api-reference/endpoints/certificate-profiles/get-by-id.mdx +++ b/docs/api-reference/endpoints/certificate-profiles/get-by-id.mdx @@ -1,4 +1,4 @@ --- title: "Get by ID" -openapi: "GET /api/v1/pki/certificate-profiles/{id}" +openapi: "GET /api/v1/cert-manager/certificate-profiles/{id}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-profiles/get-by-slug.mdx b/docs/api-reference/endpoints/certificate-profiles/get-by-slug.mdx index 9013020d6..4bcf7b73a 100644 --- a/docs/api-reference/endpoints/certificate-profiles/get-by-slug.mdx +++ b/docs/api-reference/endpoints/certificate-profiles/get-by-slug.mdx @@ -1,4 +1,4 @@ --- title: "Get by Slug" -openapi: "GET /api/v1/pki/certificate-profiles/slug/{slug}" +openapi: "GET /api/v1/cert-manager/certificate-profiles/slug/{slug}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-profiles/get-latest-active-bundle.mdx b/docs/api-reference/endpoints/certificate-profiles/get-latest-active-bundle.mdx index aa033418d..c1f3daebd 100644 --- a/docs/api-reference/endpoints/certificate-profiles/get-latest-active-bundle.mdx +++ b/docs/api-reference/endpoints/certificate-profiles/get-latest-active-bundle.mdx @@ -1,4 +1,4 @@ --- title: "Get Latest Active Certificate Bundle" -openapi: "GET /api/v1/pki/certificate-profiles/{id}/certificates/latest-active-bundle" +openapi: "GET /api/v1/cert-manager/certificate-profiles/{id}/certificates/latest-active-bundle" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-profiles/list-certificates.mdx b/docs/api-reference/endpoints/certificate-profiles/list-certificates.mdx index d0a690f76..2fac15d1d 100644 --- a/docs/api-reference/endpoints/certificate-profiles/list-certificates.mdx +++ b/docs/api-reference/endpoints/certificate-profiles/list-certificates.mdx @@ -1,4 +1,4 @@ --- title: "List Certificates" -openapi: "GET /api/v1/pki/certificate-profiles/{id}/certificates" +openapi: "GET /api/v1/cert-manager/certificate-profiles/{id}/certificates" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-profiles/list.mdx b/docs/api-reference/endpoints/certificate-profiles/list.mdx index c0f461512..869b0d805 100644 --- a/docs/api-reference/endpoints/certificate-profiles/list.mdx +++ b/docs/api-reference/endpoints/certificate-profiles/list.mdx @@ -1,4 +1,4 @@ --- title: "List" -openapi: "GET /api/v1/pki/certificate-profiles" +openapi: "GET /api/v1/cert-manager/certificate-profiles" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-profiles/update.mdx b/docs/api-reference/endpoints/certificate-profiles/update.mdx index e483cf030..c62af15e0 100644 --- a/docs/api-reference/endpoints/certificate-profiles/update.mdx +++ b/docs/api-reference/endpoints/certificate-profiles/update.mdx @@ -1,4 +1,4 @@ --- title: "Update" -openapi: "PATCH /api/v1/pki/certificate-profiles/{id}" +openapi: "PATCH /api/v1/cert-manager/certificate-profiles/{id}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-syncs/list.mdx b/docs/api-reference/endpoints/certificate-syncs/list.mdx index 6de2c2d1b..718a07379 100644 --- a/docs/api-reference/endpoints/certificate-syncs/list.mdx +++ b/docs/api-reference/endpoints/certificate-syncs/list.mdx @@ -1,4 +1,4 @@ --- title: "List PKI Syncs" -openapi: "GET /api/v1/pki/syncs" +openapi: "GET /api/v1/cert-manager/syncs" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-syncs/options.mdx b/docs/api-reference/endpoints/certificate-syncs/options.mdx index ab2d11e48..148476128 100644 --- a/docs/api-reference/endpoints/certificate-syncs/options.mdx +++ b/docs/api-reference/endpoints/certificate-syncs/options.mdx @@ -1,4 +1,4 @@ --- title: "Options" -openapi: "GET /api/v1/pki/syncs/options" +openapi: "GET /api/v1/cert-manager/syncs/options" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates-v2/create.mdx b/docs/api-reference/endpoints/certificate-templates-v2/create.mdx deleted file mode 100644 index 2fb4da177..000000000 --- a/docs/api-reference/endpoints/certificate-templates-v2/create.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Create" -openapi: "POST /api/v2/certificate-templates" ---- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates-v2/delete.mdx b/docs/api-reference/endpoints/certificate-templates-v2/delete.mdx deleted file mode 100644 index dc92ca55a..000000000 --- a/docs/api-reference/endpoints/certificate-templates-v2/delete.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Delete" -openapi: "DELETE /api/v2/certificate-templates/{id}" ---- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates-v2/get-by-id.mdx b/docs/api-reference/endpoints/certificate-templates-v2/get-by-id.mdx deleted file mode 100644 index c97389a1d..000000000 --- a/docs/api-reference/endpoints/certificate-templates-v2/get-by-id.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Get by ID" -openapi: "GET /api/v2/certificate-templates/{id}" ---- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates-v2/list.mdx b/docs/api-reference/endpoints/certificate-templates-v2/list.mdx deleted file mode 100644 index ab752e851..000000000 --- a/docs/api-reference/endpoints/certificate-templates-v2/list.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "List" -openapi: "GET /api/v2/certificate-templates" ---- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates-v2/update.mdx b/docs/api-reference/endpoints/certificate-templates-v2/update.mdx deleted file mode 100644 index 7bdeca14e..000000000 --- a/docs/api-reference/endpoints/certificate-templates-v2/update.mdx +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Update" -openapi: "PATCH /api/v2/certificate-templates/{id}" ---- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates/create.mdx b/docs/api-reference/endpoints/certificate-templates/create.mdx new file mode 100644 index 000000000..af59acd8d --- /dev/null +++ b/docs/api-reference/endpoints/certificate-templates/create.mdx @@ -0,0 +1,4 @@ +--- +title: "Create" +openapi: "POST /api/v1/cert-manager/certificate-templates" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates/delete.mdx b/docs/api-reference/endpoints/certificate-templates/delete.mdx new file mode 100644 index 000000000..9232cdef8 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-templates/delete.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete" +openapi: "DELETE /api/v1/cert-manager/certificate-templates/{id}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates/get-by-id.mdx b/docs/api-reference/endpoints/certificate-templates/get-by-id.mdx new file mode 100644 index 000000000..8691cadb0 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-templates/get-by-id.mdx @@ -0,0 +1,4 @@ +--- +title: "Get by ID" +openapi: "GET /api/v1/cert-manager/certificate-templates/{id}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates/list.mdx b/docs/api-reference/endpoints/certificate-templates/list.mdx new file mode 100644 index 000000000..5cdedb2f8 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-templates/list.mdx @@ -0,0 +1,4 @@ +--- +title: "List" +openapi: "GET /api/v1/cert-manager/certificate-templates" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificate-templates/update.mdx b/docs/api-reference/endpoints/certificate-templates/update.mdx new file mode 100644 index 000000000..229bf6d14 --- /dev/null +++ b/docs/api-reference/endpoints/certificate-templates/update.mdx @@ -0,0 +1,4 @@ +--- +title: "Update" +openapi: "PATCH /api/v1/cert-manager/certificate-templates/{id}" +--- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificates/bundle.mdx b/docs/api-reference/endpoints/certificates/bundle.mdx index 60d37a2d8..5f5b5a8b8 100644 --- a/docs/api-reference/endpoints/certificates/bundle.mdx +++ b/docs/api-reference/endpoints/certificates/bundle.mdx @@ -1,6 +1,6 @@ --- title: "Get Certificate Bundle" -openapi: "GET /api/v1/pki/certificates/{serialNumber}/bundle" +openapi: "GET /api/v1/cert-manager/certificates/{id}/bundle" --- diff --git a/docs/api-reference/endpoints/certificates/cert-body.mdx b/docs/api-reference/endpoints/certificates/cert-body.mdx index e4c3b0123..6437ef847 100644 --- a/docs/api-reference/endpoints/certificates/cert-body.mdx +++ b/docs/api-reference/endpoints/certificates/cert-body.mdx @@ -1,4 +1,4 @@ --- title: "Get Certificate Body / Chain" -openapi: "GET /api/v1/pki/certificates/{serialNumber}/certificate" +openapi: "GET /api/v1/cert-manager/certificates/{id}/certificate" --- diff --git a/docs/api-reference/endpoints/certificates/delete.mdx b/docs/api-reference/endpoints/certificates/delete.mdx index 27042af42..2b3d0a74d 100644 --- a/docs/api-reference/endpoints/certificates/delete.mdx +++ b/docs/api-reference/endpoints/certificates/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete" -openapi: "DELETE /api/v1/pki/certificates/{serialNumber}" +openapi: "DELETE /api/v1/cert-manager/certificates/{id}" --- diff --git a/docs/api-reference/endpoints/certificates/issue-certificate.mdx b/docs/api-reference/endpoints/certificates/issue-certificate.mdx index 13a464b67..b77b3caac 100644 --- a/docs/api-reference/endpoints/certificates/issue-certificate.mdx +++ b/docs/api-reference/endpoints/certificates/issue-certificate.mdx @@ -1,4 +1,4 @@ --- title: "Issue Certificate" -openapi: "POST /api/v3/pki/certificates/issue-certificate" +openapi: "POST /api/v1/cert-manager/certificates/issue-certificate" --- diff --git a/docs/api-reference/endpoints/certificates/private-key.mdx b/docs/api-reference/endpoints/certificates/private-key.mdx index d0b93e65c..858baf347 100644 --- a/docs/api-reference/endpoints/certificates/private-key.mdx +++ b/docs/api-reference/endpoints/certificates/private-key.mdx @@ -1,4 +1,4 @@ --- title: "Get Certificate Private Key" -openapi: "GET /api/v1/pki/certificates/{serialNumber}/private-key" +openapi: "GET /api/v1/cert-manager/certificates/{id}/private-key" --- diff --git a/docs/api-reference/endpoints/certificates/read.mdx b/docs/api-reference/endpoints/certificates/read.mdx index ce6463dde..d54d05d09 100644 --- a/docs/api-reference/endpoints/certificates/read.mdx +++ b/docs/api-reference/endpoints/certificates/read.mdx @@ -1,4 +1,4 @@ --- title: "Retrieve" -openapi: "GET /api/v1/pki/certificates/{serialNumber}" +openapi: "GET /api/v1/cert-manager/certificates/{id}" --- diff --git a/docs/api-reference/endpoints/certificates/renew.mdx b/docs/api-reference/endpoints/certificates/renew.mdx index b44424369..8f69be6f6 100644 --- a/docs/api-reference/endpoints/certificates/renew.mdx +++ b/docs/api-reference/endpoints/certificates/renew.mdx @@ -1,4 +1,4 @@ --- title: "Renew Certificate" -openapi: "POST /api/v3/pki/certificates/{certificateId}/renew" +openapi: "POST /api/v1/cert-manager/certificates/{id}/renew" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/certificates/revoke.mdx b/docs/api-reference/endpoints/certificates/revoke.mdx index e4da73a19..e730412df 100644 --- a/docs/api-reference/endpoints/certificates/revoke.mdx +++ b/docs/api-reference/endpoints/certificates/revoke.mdx @@ -1,4 +1,4 @@ --- title: "Revoke" -openapi: "POST /api/v1/pki/certificates/{serialNumber}/revoke" +openapi: "POST /api/v1/cert-manager/certificates/{id}/revoke" --- diff --git a/docs/api-reference/endpoints/certificates/sign-certificate.mdx b/docs/api-reference/endpoints/certificates/sign-certificate.mdx index 7291025fc..402e8ae08 100644 --- a/docs/api-reference/endpoints/certificates/sign-certificate.mdx +++ b/docs/api-reference/endpoints/certificates/sign-certificate.mdx @@ -1,4 +1,4 @@ --- title: "Sign Certificate" -openapi: "POST /api/v3/pki/certificates/sign-certificate" +openapi: "POST /api/v1/cert-manager/certificates/sign-certificate" --- diff --git a/docs/api-reference/endpoints/certificates/update-config.mdx b/docs/api-reference/endpoints/certificates/update-config.mdx index 70520bf68..cbfe76b29 100644 --- a/docs/api-reference/endpoints/certificates/update-config.mdx +++ b/docs/api-reference/endpoints/certificates/update-config.mdx @@ -1,4 +1,4 @@ --- title: "Update Certificate Config" -openapi: "PATCH /api/v3/pki/certificates/{certificateId}/config" +openapi: "PATCH /api/v1/cert-manager/certificates/{id}/config" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/add-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/add-certificates.mdx index c7b21996e..eaa0b6ca1 100644 --- a/docs/api-reference/endpoints/pki/syncs/add-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/add-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Add Certificates to Sync" -openapi: "POST /api/v1/pki/syncs/{pkiSyncId}/certificates" +openapi: "POST /api/v1/cert-manager/syncs/{pkiSyncId}/certificates" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/create.mdx b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/create.mdx index dcd58cf32..e4e84fd4c 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/create.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/create.mdx @@ -1,4 +1,4 @@ --- title: "Create AWS Certificate Manager PKI Sync" -openapi: "POST /api/v1/pki/syncs/aws-certificate-manager" +openapi: "POST /api/v1/cert-manager/syncs/aws-certificate-manager" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/delete.mdx b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/delete.mdx index 73fed2cdb..0b7bcfbb7 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/delete.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete AWS Certificate Manager PKI Sync" -openapi: "DELETE /api/v1/pki/syncs/aws-certificate-manager/{pkiSyncId}" +openapi: "DELETE /api/v1/cert-manager/syncs/aws-certificate-manager/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/get-by-id.mdx b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/get-by-id.mdx index 9191bbde3..7b3a5c14b 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/get-by-id.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/get-by-id.mdx @@ -1,4 +1,4 @@ --- title: "Get AWS Certificate Manager PKI Sync by ID" -openapi: "GET /api/v1/pki/syncs/aws-certificate-manager/{pkiSyncId}" +openapi: "GET /api/v1/cert-manager/syncs/aws-certificate-manager/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/list.mdx b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/list.mdx index 821ddbd61..e91ef9a21 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/list.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/list.mdx @@ -1,4 +1,4 @@ --- title: "List AWS Certificate Manager PKI Syncs" -openapi: "GET /api/v1/pki/syncs/aws-certificate-manager" +openapi: "GET /api/v1/cert-manager/syncs/aws-certificate-manager" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/remove-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/remove-certificates.mdx index 5ea989f2a..8d2229b68 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/remove-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/remove-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Remove Certificates from AWS Certificate Manager" -openapi: "POST /api/v1/pki/syncs/aws-certificate-manager/{pkiSyncId}/remove-certificates" +openapi: "POST /api/v1/cert-manager/syncs/aws-certificate-manager/{pkiSyncId}/remove-certificates" --- diff --git a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/sync-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/sync-certificates.mdx index b97b7a9ab..2a3fbae8d 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/sync-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/sync-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Sync Certificates to AWS Certificate Manager" -openapi: "POST /api/v1/pki/syncs/aws-certificate-manager/{pkiSyncId}/sync" +openapi: "POST /api/v1/cert-manager/syncs/aws-certificate-manager/{pkiSyncId}/sync" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/update.mdx b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/update.mdx index 9b7382ce8..22fdd5a5e 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/update.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-certificate-manager/update.mdx @@ -1,4 +1,4 @@ --- title: "Update AWS Certificate Manager PKI Sync" -openapi: "PATCH /api/v1/pki/syncs/aws-certificate-manager/{pkiSyncId}" +openapi: "PATCH /api/v1/cert-manager/syncs/aws-certificate-manager/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/create.mdx b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/create.mdx index 802a6e639..84709ff9d 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/create.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/create.mdx @@ -1,4 +1,4 @@ --- title: "Create AWS Secrets Manager PKI Sync" -openapi: "POST /api/v1/pki/syncs/aws-secrets-manager" +openapi: "POST /api/v1/cert-manager/syncs/aws-secrets-manager" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/delete.mdx b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/delete.mdx index 9912a9ee1..22751d5b7 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/delete.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete AWS Secrets Manager PKI Sync" -openapi: "DELETE /api/v1/pki/syncs/aws-secrets-manager/{pkiSyncId}" +openapi: "DELETE /api/v1/cert-manager/syncs/aws-secrets-manager/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/get-by-id.mdx b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/get-by-id.mdx index 9b678dcf5..b9e06011d 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/get-by-id.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/get-by-id.mdx @@ -1,4 +1,4 @@ --- title: "Get AWS Secrets Manager PKI Sync by ID" -openapi: "GET /api/v1/pki/syncs/aws-secrets-manager/{pkiSyncId}" +openapi: "GET /api/v1/cert-manager/syncs/aws-secrets-manager/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/list.mdx b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/list.mdx index f487770bb..5b933d548 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/list.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/list.mdx @@ -1,4 +1,4 @@ --- title: "List AWS Secrets Manager PKI Syncs" -openapi: "GET /api/v1/pki/syncs/aws-secrets-manager" +openapi: "GET /api/v1/cert-manager/syncs/aws-secrets-manager" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/remove-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/remove-certificates.mdx index f049537ab..ed725eadb 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/remove-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/remove-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Remove Certificates from AWS Secrets Manager" -openapi: "POST /api/v1/pki/syncs/aws-secrets-manager/{pkiSyncId}/remove-certificates" +openapi: "POST /api/v1/cert-manager/syncs/aws-secrets-manager/{pkiSyncId}/remove-certificates" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/sync-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/sync-certificates.mdx index acecf1b83..0af0093bb 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/sync-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/sync-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Sync Certificates to AWS Secrets Manager" -openapi: "POST /api/v1/pki/syncs/aws-secrets-manager/{pkiSyncId}/sync-certificates" +openapi: "POST /api/v1/cert-manager/syncs/aws-secrets-manager/{pkiSyncId}/sync" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/update.mdx b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/update.mdx index b123f3986..807935ee9 100644 --- a/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/update.mdx +++ b/docs/api-reference/endpoints/pki/syncs/aws-secrets-manager/update.mdx @@ -1,4 +1,4 @@ --- title: "Update AWS Secrets Manager PKI Sync" -openapi: "PATCH /api/v1/pki/syncs/aws-secrets-manager/{pkiSyncId}" +openapi: "PATCH /api/v1/cert-manager/syncs/aws-secrets-manager/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/create.mdx b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/create.mdx index 1a464cd1e..fb0118ec4 100644 --- a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/create.mdx +++ b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/create.mdx @@ -1,4 +1,4 @@ --- title: "Create Azure Key Vault PKI Sync" -openapi: "POST /api/v1/pki/syncs/azure-key-vault" +openapi: "POST /api/v1/cert-manager/syncs/azure-key-vault" --- diff --git a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/delete.mdx b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/delete.mdx index a08b2664d..0f6c686c9 100644 --- a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/delete.mdx +++ b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete Azure Key Vault PKI Sync" -openapi: "DELETE /api/v1/pki/syncs/azure-key-vault/{pkiSyncId}" +openapi: "DELETE /api/v1/cert-manager/syncs/azure-key-vault/{pkiSyncId}" --- diff --git a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/get-by-id.mdx b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/get-by-id.mdx index 0976a9dd1..7590402d4 100644 --- a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/get-by-id.mdx +++ b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/get-by-id.mdx @@ -1,4 +1,4 @@ --- title: "Get Azure Key Vault PKI Sync by ID" -openapi: "GET /api/v1/pki/syncs/azure-key-vault/{pkiSyncId}" +openapi: "GET /api/v1/cert-manager/syncs/azure-key-vault/{pkiSyncId}" --- diff --git a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/list.mdx b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/list.mdx index b21f5bc33..38b7f9f25 100644 --- a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/list.mdx +++ b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/list.mdx @@ -1,4 +1,4 @@ --- title: "List Azure Key Vault PKI Syncs" -openapi: "GET /api/v1/pki/syncs/azure-key-vault" +openapi: "GET /api/v1/cert-manager/syncs/azure-key-vault" --- diff --git a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/remove-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/remove-certificates.mdx index 817f545c0..eeb8f8116 100644 --- a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/remove-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/remove-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Remove Certificates from Azure Key Vault" -openapi: "POST /api/v1/pki/syncs/azure-key-vault/{pkiSyncId}/remove-certificates" +openapi: "POST /api/v1/cert-manager/syncs/azure-key-vault/{pkiSyncId}/remove-certificates" --- diff --git a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/sync-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/sync-certificates.mdx index ca8faced5..7fd8bebf0 100644 --- a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/sync-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/sync-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Sync Certificates to Azure Key Vault" -openapi: "POST /api/v1/pki/syncs/azure-key-vault/{pkiSyncId}/sync" +openapi: "POST /api/v1/cert-manager/syncs/azure-key-vault/{pkiSyncId}/sync" --- diff --git a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/update.mdx b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/update.mdx index bc0e903cf..084d6723e 100644 --- a/docs/api-reference/endpoints/pki/syncs/azure-key-vault/update.mdx +++ b/docs/api-reference/endpoints/pki/syncs/azure-key-vault/update.mdx @@ -1,4 +1,4 @@ --- title: "Update Azure Key Vault PKI Sync" -openapi: "PATCH /api/v1/pki/syncs/azure-key-vault/{pkiSyncId}" +openapi: "PATCH /api/v1/cert-manager/syncs/azure-key-vault/{pkiSyncId}" --- diff --git a/docs/api-reference/endpoints/pki/syncs/chef/create.mdx b/docs/api-reference/endpoints/pki/syncs/chef/create.mdx index 64807de11..caec0c714 100644 --- a/docs/api-reference/endpoints/pki/syncs/chef/create.mdx +++ b/docs/api-reference/endpoints/pki/syncs/chef/create.mdx @@ -1,4 +1,4 @@ --- title: "Create Chef PKI Sync" -openapi: "POST /api/v1/pki/syncs/chef" +openapi: "POST /api/v1/cert-manager/syncs/chef" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/chef/delete.mdx b/docs/api-reference/endpoints/pki/syncs/chef/delete.mdx index b22dbda83..78bf9c688 100644 --- a/docs/api-reference/endpoints/pki/syncs/chef/delete.mdx +++ b/docs/api-reference/endpoints/pki/syncs/chef/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete Chef PKI Sync" -openapi: "DELETE /api/v1/pki/syncs/chef/{pkiSyncId}" +openapi: "DELETE /api/v1/cert-manager/syncs/chef/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/chef/get-by-id.mdx b/docs/api-reference/endpoints/pki/syncs/chef/get-by-id.mdx index ece07770e..d0e02566e 100644 --- a/docs/api-reference/endpoints/pki/syncs/chef/get-by-id.mdx +++ b/docs/api-reference/endpoints/pki/syncs/chef/get-by-id.mdx @@ -1,4 +1,4 @@ --- title: "Get Chef PKI Sync by ID" -openapi: "GET /api/v1/pki/syncs/chef/{pkiSyncId}" +openapi: "GET /api/v1/cert-manager/syncs/chef/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/chef/list.mdx b/docs/api-reference/endpoints/pki/syncs/chef/list.mdx index 8e00bed46..84f745b2d 100644 --- a/docs/api-reference/endpoints/pki/syncs/chef/list.mdx +++ b/docs/api-reference/endpoints/pki/syncs/chef/list.mdx @@ -1,4 +1,4 @@ --- title: "List Chef PKI Syncs" -openapi: "GET /api/v1/pki/syncs/chef" +openapi: "GET /api/v1/cert-manager/syncs/chef" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/chef/remove-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/chef/remove-certificates.mdx index f4bb6816a..c8fe5d50a 100644 --- a/docs/api-reference/endpoints/pki/syncs/chef/remove-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/chef/remove-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Remove Certificates from Chef" -openapi: "POST /api/v1/pki/syncs/chef/{pkiSyncId}/remove-certificates" +openapi: "POST /api/v1/cert-manager/syncs/chef/{pkiSyncId}/remove-certificates" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/chef/sync-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/chef/sync-certificates.mdx index 109248d8a..458f58cfa 100644 --- a/docs/api-reference/endpoints/pki/syncs/chef/sync-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/chef/sync-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Sync Certificates to Chef" -openapi: "POST /api/v1/pki/syncs/chef/{pkiSyncId}/sync" +openapi: "POST /api/v1/cert-manager/syncs/chef/{pkiSyncId}/sync" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/chef/update.mdx b/docs/api-reference/endpoints/pki/syncs/chef/update.mdx index 2d08b40e9..ad78c8c66 100644 --- a/docs/api-reference/endpoints/pki/syncs/chef/update.mdx +++ b/docs/api-reference/endpoints/pki/syncs/chef/update.mdx @@ -1,4 +1,4 @@ --- title: "Update Chef PKI Sync" -openapi: "PATCH /api/v1/pki/syncs/chef/{pkiSyncId}" +openapi: "PATCH /api/v1/cert-manager/syncs/chef/{pkiSyncId}" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/get-by-id.mdx b/docs/api-reference/endpoints/pki/syncs/get-by-id.mdx index 6ec710ec8..73131deba 100644 --- a/docs/api-reference/endpoints/pki/syncs/get-by-id.mdx +++ b/docs/api-reference/endpoints/pki/syncs/get-by-id.mdx @@ -1,4 +1,4 @@ --- title: "Get PKI Sync by ID" -openapi: "GET /api/v1/pki/syncs/{pkiSyncId}" +openapi: "GET /api/v1/cert-manager/syncs/{pkiSyncId}" --- diff --git a/docs/api-reference/endpoints/pki/syncs/list-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/list-certificates.mdx index eaece0a2d..994803c0b 100644 --- a/docs/api-reference/endpoints/pki/syncs/list-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/list-certificates.mdx @@ -1,4 +1,4 @@ --- title: "List Sync Certificates" -openapi: "GET /api/v1/pki/syncs/{pkiSyncId}/certificates" +openapi: "GET /api/v1/cert-manager/syncs/{pkiSyncId}/certificates" --- \ No newline at end of file diff --git a/docs/api-reference/endpoints/pki/syncs/list.mdx b/docs/api-reference/endpoints/pki/syncs/list.mdx index 4b1f1972a..6ac0e4841 100644 --- a/docs/api-reference/endpoints/pki/syncs/list.mdx +++ b/docs/api-reference/endpoints/pki/syncs/list.mdx @@ -1,4 +1,4 @@ --- title: "List PKI Syncs" -openapi: "GET /api/v1/pki/syncs" +openapi: "GET /api/v1/cert-manager/syncs" --- diff --git a/docs/api-reference/endpoints/pki/syncs/options.mdx b/docs/api-reference/endpoints/pki/syncs/options.mdx index a328b0832..b615aa4b6 100644 --- a/docs/api-reference/endpoints/pki/syncs/options.mdx +++ b/docs/api-reference/endpoints/pki/syncs/options.mdx @@ -1,4 +1,4 @@ --- title: "List PKI Sync Options" -openapi: "GET /api/v1/pki/syncs/options" +openapi: "GET /api/v1/cert-manager/syncs/options" --- diff --git a/docs/api-reference/endpoints/pki/syncs/remove-certificates.mdx b/docs/api-reference/endpoints/pki/syncs/remove-certificates.mdx index 99c8bfe28..ed5dbf70a 100644 --- a/docs/api-reference/endpoints/pki/syncs/remove-certificates.mdx +++ b/docs/api-reference/endpoints/pki/syncs/remove-certificates.mdx @@ -1,4 +1,4 @@ --- title: "Remove Certificates from Sync" -openapi: "DELETE /api/v1/pki/syncs/{pkiSyncId}/certificates" +openapi: "DELETE /api/v1/cert-manager/syncs/{pkiSyncId}/certificates" --- \ No newline at end of file diff --git a/docs/docs.json b/docs/docs.json index 57f44596f..80ca37c92 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -2530,21 +2530,16 @@ "api-reference/endpoints/certificate-authorities/internal/create", "api-reference/endpoints/certificate-authorities/internal/read", "api-reference/endpoints/certificate-authorities/internal/update", - "api-reference/endpoints/certificate-authorities/internal/delete" + "api-reference/endpoints/certificate-authorities/internal/delete", + "api-reference/endpoints/certificate-authorities/internal/renew", + "api-reference/endpoints/certificate-authorities/internal/list-ca-certs", + "api-reference/endpoints/certificate-authorities/internal/csr", + "api-reference/endpoints/certificate-authorities/internal/cert", + "api-reference/endpoints/certificate-authorities/internal/sign-intermediate", + "api-reference/endpoints/certificate-authorities/internal/import-cert", + "api-reference/endpoints/certificate-authorities/internal/crl" ] - }, - "api-reference/endpoints/certificate-authorities/list", - "api-reference/endpoints/certificate-authorities/create", - "api-reference/endpoints/certificate-authorities/read", - "api-reference/endpoints/certificate-authorities/update", - "api-reference/endpoints/certificate-authorities/delete", - "api-reference/endpoints/certificate-authorities/renew", - "api-reference/endpoints/certificate-authorities/list-ca-certs", - "api-reference/endpoints/certificate-authorities/csr", - "api-reference/endpoints/certificate-authorities/cert", - "api-reference/endpoints/certificate-authorities/sign-intermediate", - "api-reference/endpoints/certificate-authorities/import-cert", - "api-reference/endpoints/certificate-authorities/crl" + } ] }, { @@ -2566,23 +2561,11 @@ { "group": "Certificate Templates", "pages": [ - "api-reference/endpoints/certificate-templates-v2/list", - "api-reference/endpoints/certificate-templates-v2/create", - "api-reference/endpoints/certificate-templates-v2/update", - "api-reference/endpoints/certificate-templates-v2/get-by-id", - "api-reference/endpoints/certificate-templates-v2/delete" - ] - }, - { - "group": "Certificate Collections", - "pages": [ - "api-reference/endpoints/pki-collections/create", - "api-reference/endpoints/pki-collections/read", - "api-reference/endpoints/pki-collections/update", - "api-reference/endpoints/pki-collections/delete", - "api-reference/endpoints/pki-collections/add-item", - "api-reference/endpoints/pki-collections/list-items", - "api-reference/endpoints/pki-collections/delete-item" + "api-reference/endpoints/certificate-templates/list", + "api-reference/endpoints/certificate-templates/create", + "api-reference/endpoints/certificate-templates/update", + "api-reference/endpoints/certificate-templates/get-by-id", + "api-reference/endpoints/certificate-templates/delete" ] }, { diff --git a/docs/documentation/platform/pki/ca/acme-ca.mdx b/docs/documentation/platform/pki/ca/acme-ca.mdx index 774590c73..391afa179 100644 --- a/docs/documentation/platform/pki/ca/acme-ca.mdx +++ b/docs/documentation/platform/pki/ca/acme-ca.mdx @@ -153,7 +153,7 @@ In the following steps, we explore how to connect Infisical to an ACME-compatibl ### Sample request ```bash Request - curl 'https://app.infisical.com/api/v1/pki/ca/acme' \ + curl 'https://app.infisical.com/api/v1/cert-manager/ca/acme' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data-raw '{ diff --git a/docs/documentation/platform/pki/ca/private-ca.mdx b/docs/documentation/platform/pki/ca/private-ca.mdx index 74913d4cc..67b38b455 100644 --- a/docs/documentation/platform/pki/ca/private-ca.mdx +++ b/docs/documentation/platform/pki/ca/private-ca.mdx @@ -122,7 +122,7 @@ consisting of an (optional) root CA and an intermediate CA. ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/ca' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/ca/internal' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ @@ -155,7 +155,7 @@ consisting of an (optional) root CA and an intermediate CA. ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/ca' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/ca/internal' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ @@ -183,7 +183,7 @@ consisting of an (optional) root CA and an intermediate CA. ### Sample request ```bash Request - curl --location --request GET 'https://app.infisical.com/api/v1/pki/ca//csr' \ + curl --location --request GET 'https://app.infisical.com/api/v1/cert-manager/ca/internal//csr' \ --header 'Authorization: Bearer ' \ --data-raw '' ``` @@ -204,7 +204,7 @@ consisting of an (optional) root CA and an intermediate CA. ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/ca//sign-intermediate' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/ca/internal//sign-intermediate' \ --header 'Content-Type: application/json' \ --data-raw '{ "csr": "", @@ -234,7 +234,7 @@ consisting of an (optional) root CA and an intermediate CA. ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/ca//import-certificate' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/ca/internal//import-certificate' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ @@ -292,7 +292,7 @@ the certificate back to the intermediate CA. ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/ca//renew' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/ca/internal//renew' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ diff --git a/docs/documentation/platform/pki/certificate-syncs/aws-certificate-manager.mdx b/docs/documentation/platform/pki/certificate-syncs/aws-certificate-manager.mdx index e2cad7498..22285be8e 100644 --- a/docs/documentation/platform/pki/certificate-syncs/aws-certificate-manager.mdx +++ b/docs/documentation/platform/pki/certificate-syncs/aws-certificate-manager.mdx @@ -70,7 +70,7 @@ These permissions allow Infisical to list, import, tag, and manage certificates ```bash Request curl --request POST \ - --url https://app.infisical.com/api/v1/pki/syncs/aws-certificate-manager \ + --url https://app.infisical.com/api/v1/cert-manager/syncs/aws-certificate-manager \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ diff --git a/docs/documentation/platform/pki/certificate-syncs/aws-secrets-manager.mdx b/docs/documentation/platform/pki/certificate-syncs/aws-secrets-manager.mdx index 26472ce44..86461bb93 100644 --- a/docs/documentation/platform/pki/certificate-syncs/aws-secrets-manager.mdx +++ b/docs/documentation/platform/pki/certificate-syncs/aws-secrets-manager.mdx @@ -102,7 +102,7 @@ Any role with these permissions would work such as a custom policy with **Secret ```bash Request curl --request POST \ - --url https://app.infisical.com/api/v1/pki/syncs/aws-secrets-manager \ + --url https://app.infisical.com/api/v1/cert-manager/syncs/aws-secrets-manager \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ @@ -140,7 +140,7 @@ Any role with these permissions would work such as a custom policy with **Secret ```bash Request curl --request POST \ - --url https://app.infisical.com/api/v1/pki/syncs/aws-secrets-manager \ + --url https://app.infisical.com/api/v1/cert-manager/syncs/aws-secrets-manager \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ diff --git a/docs/documentation/platform/pki/certificate-syncs/azure-key-vault.mdx b/docs/documentation/platform/pki/certificate-syncs/azure-key-vault.mdx index 135c74112..4c6c81bc0 100644 --- a/docs/documentation/platform/pki/certificate-syncs/azure-key-vault.mdx +++ b/docs/documentation/platform/pki/certificate-syncs/azure-key-vault.mdx @@ -77,7 +77,7 @@ Any role with these permissions would work such as the **Key Vault Certificates ```bash Request curl --request POST \ - --url https://app.infisical.com/api/v1/pki/syncs/azure-key-vault \ + --url https://app.infisical.com/api/v1/cert-manager/syncs/azure-key-vault \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ diff --git a/docs/documentation/platform/pki/certificate-syncs/chef.mdx b/docs/documentation/platform/pki/certificate-syncs/chef.mdx index 506a2c76a..ec3eedafd 100644 --- a/docs/documentation/platform/pki/certificate-syncs/chef.mdx +++ b/docs/documentation/platform/pki/certificate-syncs/chef.mdx @@ -103,7 +103,7 @@ Any role with these permissions would work such as a custom role with **Data Bag ```bash Request curl --request POST \ - --url https://app.infisical.com/api/v1/pki/syncs/chef \ + --url https://app.infisical.com/api/v1/cert-manager/syncs/chef \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ @@ -140,7 +140,7 @@ Any role with these permissions would work such as a custom role with **Data Bag ```bash Request curl --request POST \ - --url https://app.infisical.com/api/v1/pki/syncs/chef \ + --url https://app.infisical.com/api/v1/cert-manager/syncs/chef \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ diff --git a/docs/documentation/platform/pki/certificates.mdx b/docs/documentation/platform/pki/certificates.mdx index de8de4541..112587435 100644 --- a/docs/documentation/platform/pki/certificates.mdx +++ b/docs/documentation/platform/pki/certificates.mdx @@ -260,7 +260,7 @@ In the following steps, we explore how to issue a X.509 certificate under a CA. ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/certificates/sign-certificate' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/certificates/sign-certificate' \ --header 'Content-Type: application/json' \ --data-raw '{ "certificateTemplateId": "", @@ -337,7 +337,7 @@ openssl verify -verbose -crl_check -crl_download -CAfile chain.pem cert.pem ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/certificates//revoke' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/certificates//revoke' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ @@ -362,7 +362,7 @@ openssl verify -verbose -crl_check -crl_download -CAfile chain.pem cert.pem ### Sample request ```bash Request - curl --location --request GET 'https://app.infisical.com/api/v1/pki/ca//crls' \ + curl --location --request GET 'https://app.infisical.com/api/v1/cert-manager/ca/internal//crls' \ --header 'Authorization: Bearer ' ``` diff --git a/docs/documentation/platform/pki/certificates/certificates.mdx b/docs/documentation/platform/pki/certificates/certificates.mdx index abe198750..97191f83d 100644 --- a/docs/documentation/platform/pki/certificates/certificates.mdx +++ b/docs/documentation/platform/pki/certificates/certificates.mdx @@ -220,7 +220,7 @@ openssl verify -verbose -crl_check -crl_download -CAfile chain.pem cert.pem ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/certificates//revoke' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/certificates//revoke' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ @@ -245,7 +245,7 @@ openssl verify -verbose -crl_check -crl_download -CAfile chain.pem cert.pem ### Sample request ```bash Request - curl --location --request GET 'https://app.infisical.com/api/v1/pki/ca//crls' \ + curl --location --request GET 'https://app.infisical.com/api/v1/cert-manager/ca/internal//crls' \ --header 'Authorization: Bearer ' ``` diff --git a/docs/documentation/platform/pki/enrollment-methods/acme.mdx b/docs/documentation/platform/pki/enrollment-methods/acme.mdx index 12c4779b5..d404aa922 100644 --- a/docs/documentation/platform/pki/enrollment-methods/acme.mdx +++ b/docs/documentation/platform/pki/enrollment-methods/acme.mdx @@ -47,7 +47,7 @@ In the following steps, we explore how to issue a X.509 certificate using the AC ```bash sudo certbot certonly \ --standalone \ - --server "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" \ + --server "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" \ --eab-kid "your-eab-kid" \ --eab-hmac-key "your-eab-secret" \ -d example.infisical.com \ diff --git a/docs/documentation/platform/pki/enrollment-methods/api.mdx b/docs/documentation/platform/pki/enrollment-methods/api.mdx index 304bafefc..288ae08ba 100644 --- a/docs/documentation/platform/pki/enrollment-methods/api.mdx +++ b/docs/documentation/platform/pki/enrollment-methods/api.mdx @@ -61,7 +61,7 @@ Here, select the certificate profile from step 1 that will be used to issue the ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v1/pki/certificate-profiles' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/certificate-profiles' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ diff --git a/docs/documentation/platform/pki/integration-guides/apache-certbot.mdx b/docs/documentation/platform/pki/integration-guides/apache-certbot.mdx index 78f0301e1..370c04547 100644 --- a/docs/documentation/platform/pki/integration-guides/apache-certbot.mdx +++ b/docs/documentation/platform/pki/integration-guides/apache-certbot.mdx @@ -29,7 +29,7 @@ Before you begin, make sure you have: From the ACME configuration, gather the following values: - - ACME Directory URL: The URL that Certbot will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory`. + - ACME Directory URL: The URL that Certbot will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory`. - EAB Key Identifier (KID): A unique identifier that tells Infisical which ACME account is making the request. - EAB Secret: A secret key that authenticates your ACME client with Infisical. @@ -56,7 +56,7 @@ Before you begin, make sure you have: ```bash sudo certbot certonly \ --apache \ - --server "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" \ + --server "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" \ --eab-kid "your-eab-key-identifier" \ --eab-hmac-key "your-eab-secret" \ -d example.infisical.com \ diff --git a/docs/documentation/platform/pki/integration-guides/jboss-certbot.mdx b/docs/documentation/platform/pki/integration-guides/jboss-certbot.mdx index c0e1c896b..c9a5133c0 100644 --- a/docs/documentation/platform/pki/integration-guides/jboss-certbot.mdx +++ b/docs/documentation/platform/pki/integration-guides/jboss-certbot.mdx @@ -30,7 +30,7 @@ Before you begin, make sure you have: From the ACME configuration, gather the following values: - - ACME Directory URL: The URL that Certbot will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory`. + - ACME Directory URL: The URL that Certbot will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory`. - EAB Key Identifier (KID): A unique identifier that tells Infisical which ACME account is making the request. - EAB Secret: A secret key that authenticates your ACME client with Infisical. @@ -67,7 +67,7 @@ Before you begin, make sure you have: ```bash sudo certbot certonly \ --standalone \ - --server "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" \ + --server "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" \ --eab-kid "your-eab-key-identifier" \ --eab-hmac-key "your-eab-secret" \ -d example.infisical.com \ diff --git a/docs/documentation/platform/pki/integration-guides/nginx-certbot.mdx b/docs/documentation/platform/pki/integration-guides/nginx-certbot.mdx index f28e5ee09..a91da37cf 100644 --- a/docs/documentation/platform/pki/integration-guides/nginx-certbot.mdx +++ b/docs/documentation/platform/pki/integration-guides/nginx-certbot.mdx @@ -29,7 +29,7 @@ Before you begin, make sure you have: From the ACME configuration, gather the following values: - - ACME Directory URL: The URL that Certbot will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory`. + - ACME Directory URL: The URL that Certbot will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory`. - EAB Key Identifier (KID): A unique identifier that tells Infisical which ACME account is making the request. - EAB Secret: A secret key that authenticates your ACME client with Infisical. @@ -56,7 +56,7 @@ Before you begin, make sure you have: ```bash sudo certbot certonly \ --nginx \ - --server "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" \ + --server "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" \ --eab-kid "your-eab-key-identifier" \ --eab-hmac-key "your-eab-secret" \ -d example.infisical.com \ diff --git a/docs/documentation/platform/pki/integration-guides/tomcat-certbot.mdx b/docs/documentation/platform/pki/integration-guides/tomcat-certbot.mdx index ffb07bf1b..c5ac2f989 100644 --- a/docs/documentation/platform/pki/integration-guides/tomcat-certbot.mdx +++ b/docs/documentation/platform/pki/integration-guides/tomcat-certbot.mdx @@ -29,7 +29,7 @@ Before you begin, make sure you have: From the ACME configuration, gather the following values: - - ACME Directory URL: The URL that Certbot will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory`. + - ACME Directory URL: The URL that Certbot will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory`. - EAB Key Identifier (KID): A unique identifier that tells Infisical which ACME account is making the request. - EAB Secret: A secret key that authenticates your ACME client with Infisical. @@ -64,7 +64,7 @@ Before you begin, make sure you have: ```bash sudo certbot certonly \ --standalone \ - --server "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" \ + --server "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" \ --eab-kid "your-eab-key-identifier" \ --eab-hmac-key "your-eab-secret" \ -d example.infisical.com \ diff --git a/docs/documentation/platform/pki/integration-guides/windows-server-acme.mdx b/docs/documentation/platform/pki/integration-guides/windows-server-acme.mdx index 2aab0870d..40e8b842c 100644 --- a/docs/documentation/platform/pki/integration-guides/windows-server-acme.mdx +++ b/docs/documentation/platform/pki/integration-guides/windows-server-acme.mdx @@ -28,7 +28,7 @@ Before you begin, make sure you have: From the ACME configuration, gather the following values: - - ACME Directory URL: The URL that win-acme will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory`. + - ACME Directory URL: The URL that win-acme will use to communicate with Infisical's ACME server. This takes the form `https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory`. - EAB Key Identifier (KID): A unique identifier that tells Infisical which ACME account is making the request. - EAB Secret: A secret key that authenticates your ACME client with Infisical. @@ -67,7 +67,7 @@ Before you begin, make sure you have: Run the following win-acme command to request a certificate from Infisical: ```powershell - wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store pemfiles --pemfilespath "C:\certificates" --verbose + wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store pemfiles --pemfilespath "C:\certificates" --verbose ``` For guidance on each parameter: @@ -87,7 +87,7 @@ Before you begin, make sure you have: Replace the placeholder values with your actual configuration: - `example.infisical.com`: Your actual domain name - - `https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory`: Your Infisical ACME endpoint from Step 1 + - `https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory`: Your Infisical ACME endpoint from Step 1 - `your-eab-key-identifier` and `your-eab-secret`: Your External Account Binding credentials from Step 1 - `C:\certificates`: Your desired certificate storage location @@ -101,21 +101,21 @@ Before you begin, make sure you have: Store certificates directly in the [Windows Certificate Store](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores) for integration with IIS and other Windows services: ```powershell - wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store certificatestore --verbose + wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store certificatestore --verbose ``` Generate [PFX files](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certutil) with password protection for easy deployment across Windows environments: ```powershell - wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store pfxfile --pfxfilepath "C:\certificates" --pfxpassword "your-secure-password" --verbose + wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store pfxfile --pfxfilepath "C:\certificates" --pfxpassword "your-secure-password" --verbose ``` For IIS Central SSL store integration in high-scale environments: ```powershell - wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store centralssl --centralsslstore "C:\CentralSSL" --verbose + wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store centralssl --centralsslstore "C:\CentralSSL" --verbose ``` @@ -129,7 +129,7 @@ Before you begin, make sure you have: Include the `--setuptaskscheduler` parameter in your initial command to automatically create the renewal task: ```powershell - wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/pki/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store pemfiles --pemfilespath "C:\certificates" --setuptaskscheduler --verbose + wacs.exe --target manual --host example.infisical.com --baseuri "https://your-infisical-instance.com/api/v1/cert-manager/certificate-profiles/{profile-id}/acme/directory" --eab-key-identifier "your-eab-key-identifier" --eab-key "your-eab-secret" --validation selfhosting --store pemfiles --pemfilespath "C:\certificates" --setuptaskscheduler --verbose ``` **Option 2: Test manual renewal** From d434d4ec702b44b6cb46e886f6234ee5ff992358 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Wed, 26 Nov 2025 04:29:24 +0800 Subject: [PATCH 3/8] misc: added cert alerts to doc --- backend/src/server/routes/v1/pki-alert-router.ts | 7 +++++++ docs/api-reference/endpoints/pki-alerts/create.mdx | 2 +- docs/api-reference/endpoints/pki-alerts/delete.mdx | 2 +- docs/api-reference/endpoints/pki-alerts/read.mdx | 2 +- docs/api-reference/endpoints/pki-alerts/update.mdx | 2 +- docs/docs.json | 9 +++++++++ 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/backend/src/server/routes/v1/pki-alert-router.ts b/backend/src/server/routes/v1/pki-alert-router.ts index 459b5cc6c..a786e6015 100644 --- a/backend/src/server/routes/v1/pki-alert-router.ts +++ b/backend/src/server/routes/v1/pki-alert-router.ts @@ -23,6 +23,7 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + hide: false, description: "Create a new PKI alert", tags: [ApiDocsTags.PkiAlerting], body: CreatePkiAlertV2Schema.extend({ @@ -90,6 +91,7 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + hide: false, description: "List PKI alerts for a project", tags: [ApiDocsTags.PkiAlerting], querystring: z.object({ @@ -150,6 +152,7 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + hide: false, description: "Get a PKI alert by ID", tags: [ApiDocsTags.PkiAlerting], params: z.object({ @@ -214,6 +217,7 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + hide: false, description: "Update a PKI alert", tags: [ApiDocsTags.PkiAlerting], params: z.object({ @@ -283,6 +287,7 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + hide: false, description: "Delete a PKI alert", tags: [ApiDocsTags.PkiAlerting], params: z.object({ @@ -347,6 +352,7 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + hide: false, description: "List certificates that match an alert's filter rules", tags: [ApiDocsTags.PkiAlerting], params: z.object({ @@ -397,6 +403,7 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), schema: { + hide: false, description: "Preview certificates that would match the given filter rules", tags: [ApiDocsTags.PkiAlerting], body: z.object({ diff --git a/docs/api-reference/endpoints/pki-alerts/create.mdx b/docs/api-reference/endpoints/pki-alerts/create.mdx index d4be026a7..e339dd425 100644 --- a/docs/api-reference/endpoints/pki-alerts/create.mdx +++ b/docs/api-reference/endpoints/pki-alerts/create.mdx @@ -1,4 +1,4 @@ --- title: "Create" -openapi: "POST /api/v2/pki/alerts" +openapi: "POST /api/v1/cert-manager/alerts" --- diff --git a/docs/api-reference/endpoints/pki-alerts/delete.mdx b/docs/api-reference/endpoints/pki-alerts/delete.mdx index 67429049c..8cf3b8e40 100644 --- a/docs/api-reference/endpoints/pki-alerts/delete.mdx +++ b/docs/api-reference/endpoints/pki-alerts/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete" -openapi: "DELETE /api/v2/pki/alerts/{alertId}" +openapi: "DELETE /api/v1/cert-manager/alerts/{alertId}" --- diff --git a/docs/api-reference/endpoints/pki-alerts/read.mdx b/docs/api-reference/endpoints/pki-alerts/read.mdx index 0e0547288..b408e1709 100644 --- a/docs/api-reference/endpoints/pki-alerts/read.mdx +++ b/docs/api-reference/endpoints/pki-alerts/read.mdx @@ -1,4 +1,4 @@ --- title: "Retrieve" -openapi: "GET /api/v2/pki/alerts/{alertId}" +openapi: "GET /api/v1/cert-manager/alerts/{alertId}" --- diff --git a/docs/api-reference/endpoints/pki-alerts/update.mdx b/docs/api-reference/endpoints/pki-alerts/update.mdx index 45f1f1f1f..8e4dbb574 100644 --- a/docs/api-reference/endpoints/pki-alerts/update.mdx +++ b/docs/api-reference/endpoints/pki-alerts/update.mdx @@ -1,4 +1,4 @@ --- title: "Update" -openapi: "PATCH /api/v2/pki/alerts/{alertId}" +openapi: "PATCH /api/v1/cert-manager/alerts/{alertId}" --- diff --git a/docs/docs.json b/docs/docs.json index 80ca37c92..bde82d71f 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -2581,6 +2581,15 @@ "api-reference/endpoints/certificate-profiles/get-latest-active-bundle" ] }, + { + "group": "Certificate Alerts", + "pages": [ + "api-reference/endpoints/pki-alerts/create", + "api-reference/endpoints/pki-alerts/read", + "api-reference/endpoints/pki-alerts/update", + "api-reference/endpoints/pki-alerts/delete" + ] + }, { "group": "Certificate Syncs", "pages": [ From f1ac487d491eda0b314a72db215266297e85b1e9 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Wed, 26 Nov 2025 04:32:04 +0800 Subject: [PATCH 4/8] misc: updated test --- backend/bdd/features/pki/acme/external-ca.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/bdd/features/pki/acme/external-ca.feature b/backend/bdd/features/pki/acme/external-ca.feature index 6b8025308..2a900dd10 100644 --- a/backend/bdd/features/pki/acme/external-ca.feature +++ b/backend/bdd/features/pki/acme/external-ca.feature @@ -271,7 +271,7 @@ Feature: External CA """ Then I memorize cert_template with jq ".certificateTemplate.id" as cert_template_id Given I create an ACME profile with ca {ext_ca_id} and template {cert_template_id} as "acme_profile" - When I have an ACME client connecting to "{BASE_URL}/api/v1/pki/acme/profiles/{acme_profile.id}/directory" + When I have an ACME client connecting to "{BASE_URL}/api/v1/cert-manager/acme/profiles/{acme_profile.id}/directory" Then I register a new ACME account with email fangpen@infisical.com and EAB key id "{acme_profile.eab_kid}" with secret "{acme_profile.eab_secret}" as acme_account When I create certificate signing request as csr Then I add names to certificate signing request csr From 96d36bf1a6effa751e9b4b22802e2c6e101b7368 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Wed, 26 Nov 2025 22:45:49 +0800 Subject: [PATCH 5/8] misc: resolved export for pkcs12 --- .../certificate/certificate-service.ts | 2 +- .../src/hooks/api/certificates/mutations.tsx | 6 ++-- frontend/src/hooks/api/certificates/types.ts | 2 +- .../components/CertificateExportModal.tsx | 28 +++++++++++++++---- .../components/CertificatesSection.tsx | 10 +++++-- .../components/CertificatesTable.tsx | 1 + 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/backend/src/services/certificate/certificate-service.ts b/backend/src/services/certificate/certificate-service.ts index 983bf3f46..44be47fc7 100644 --- a/backend/src/services/certificate/certificate-service.ts +++ b/backend/src/services/certificate/certificate-service.ts @@ -731,7 +731,7 @@ export const certificateServiceFactory = ({ // Get certificate bundle (certificate, chain, private key) const { certificate, certificateChain, privateKey } = await getCertBundle({ - serialNumber, + id: cert.id, actor, actorId, actorAuthMethod, diff --git a/frontend/src/hooks/api/certificates/mutations.tsx b/frontend/src/hooks/api/certificates/mutations.tsx index aca752458..54aa3c3b4 100644 --- a/frontend/src/hooks/api/certificates/mutations.tsx +++ b/frontend/src/hooks/api/certificates/mutations.tsx @@ -149,10 +149,10 @@ export const useUpdateRenewalConfig = () => { export const useDownloadCertPkcs12 = () => { return useMutation({ - mutationFn: async ({ serialNumber, projectSlug, password, alias }) => { + mutationFn: async ({ certificateId, projectSlug, password, alias }) => { try { const response = await apiRequest.post( - `/api/v1/cert-manager/certificates/${serialNumber}/pkcs12`, + `/api/v1/cert-manager/certificates/${certificateId}/pkcs12`, { password, alias @@ -168,7 +168,7 @@ export const useDownloadCertPkcs12 = () => { const url = window.URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; - link.download = `certificate-${serialNumber}.p12`; + link.download = `certificate-${certificateId}.p12`; document.body.appendChild(link); link.click(); document.body.removeChild(link); diff --git a/frontend/src/hooks/api/certificates/types.ts b/frontend/src/hooks/api/certificates/types.ts index 953ae818f..2e9b70cae 100644 --- a/frontend/src/hooks/api/certificates/types.ts +++ b/frontend/src/hooks/api/certificates/types.ts @@ -74,7 +74,7 @@ export type TUpdateRenewalConfigDTO = { }; export type TDownloadPkcs12DTO = { - serialNumber: string; + certificateId: string; projectSlug: string; password: string; alias: string; diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateExportModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateExportModal.tsx index 3916477a1..d16a1ac3f 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateExportModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateExportModal.tsx @@ -21,7 +21,13 @@ type Props = { ) => void; onFormatSelected: ( format: "pem" | "pkcs12", - serialNumber: string, + { + certificateId, + serialNumber + }: { + certificateId: string; + serialNumber: string; + }, options?: ExportOptions ) => void; }; @@ -42,8 +48,11 @@ export const CertificateExportModal = ({ popUp, handlePopUpToggle, onFormatSelec alias: "" }); - const serialNumber = - (popUp?.certificateExport?.data as { serialNumber: string })?.serialNumber || ""; + const { certificateId, serialNumber } = + (popUp?.certificateExport?.data as { + certificateId: string; + serialNumber: string; + }) || {}; // Reset form whenever the modal opens useEffect(() => { @@ -64,14 +73,21 @@ export const CertificateExportModal = ({ popUp, handlePopUpToggle, onFormatSelec }; const handleExport = () => { - if (serialNumber && isFormValid()) { + if ((certificateId || serialNumber) && isFormValid()) { const options: ExportOptions = {}; if (selectedFormat === "pkcs12") { options.pkcs12 = pkcs12Options; } - onFormatSelected(selectedFormat, serialNumber, options); + onFormatSelected( + selectedFormat, + { + certificateId, + serialNumber + }, + options + ); handlePopUpToggle("certificateExport", false); } }; @@ -151,7 +167,7 @@ export const CertificateExportModal = ({ popUp, handlePopUpToggle, onFormatSelec colorSchema="primary" leftIcon={} onClick={handleExport} - disabled={!serialNumber || !isFormValid()} + disabled={!(certificateId || serialNumber) || !isFormValid()} > Export {selectedFormat.toUpperCase()} diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx index 36c4b4f71..54967b2b2 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesSection.tsx @@ -57,7 +57,13 @@ export const CertificatesSection = () => { const handleCertificateExport = async ( format: "pem" | "pkcs12", - serialNumber: string, + { + certificateId, + serialNumber + }: { + certificateId: string; + serialNumber: string; + }, options?: ExportOptions ) => { if (format === "pem") { @@ -75,7 +81,7 @@ export const CertificatesSection = () => { try { await downloadCertPkcs12({ - serialNumber, + certificateId, projectSlug: currentProject.slug, password: options.pkcs12.password, alias: options.pkcs12.alias diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx index e6d10bcd6..b4defeb3a 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificatesTable.tsx @@ -277,6 +277,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => { )} onClick={async () => handlePopUpOpen("certificateExport", { + certificateId: certificate.id, serialNumber: certificate.serialNumber }) } From b5e2547af04569dc18aa1b8fa8793da04c7808be Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Fri, 28 Nov 2025 04:33:14 +0800 Subject: [PATCH 6/8] misc: addressed comments --- .../platform/pki/certificates.mdx | 2 +- .../platform/pki/enrollment-methods/api.mdx | 4 +-- frontend/src/hooks/api/ca/types.ts | 5 +++- .../api/certificateTemplates/mutations.tsx | 6 ++-- .../api/certificateTemplates/queries.tsx | 2 +- .../components/CaDetailsSection.tsx | 4 --- .../components/ExternalCaModal.tsx | 30 +------------------ 7 files changed, 12 insertions(+), 41 deletions(-) diff --git a/docs/documentation/platform/pki/certificates.mdx b/docs/documentation/platform/pki/certificates.mdx index 112587435..da73de37d 100644 --- a/docs/documentation/platform/pki/certificates.mdx +++ b/docs/documentation/platform/pki/certificates.mdx @@ -221,7 +221,7 @@ In the following steps, we explore how to issue a X.509 certificate under a CA. ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v3/pki/certificates/issue-certificate' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/certificates/issue-certificate' \ --header 'Content-Type: application/json' \ --data-raw '{ "profileId": "", diff --git a/docs/documentation/platform/pki/enrollment-methods/api.mdx b/docs/documentation/platform/pki/enrollment-methods/api.mdx index 288ae08ba..bfbac7f2e 100644 --- a/docs/documentation/platform/pki/enrollment-methods/api.mdx +++ b/docs/documentation/platform/pki/enrollment-methods/api.mdx @@ -105,7 +105,7 @@ Here, select the certificate profile from step 1 that will be used to issue the ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v3/pki/certificates/issue-certificate' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/certificates/issue-certificate' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ @@ -151,7 +151,7 @@ Here, select the certificate profile from step 1 that will be used to issue the ### Sample request ```bash Request - curl --location --request POST 'https://app.infisical.com/api/v3/pki/certificates/sign-certificate' \ + curl --location --request POST 'https://app.infisical.com/api/v1/cert-manager/certificates/sign-certificate' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data-raw '{ diff --git a/frontend/src/hooks/api/ca/types.ts b/frontend/src/hooks/api/ca/types.ts index a07499975..57af49259 100644 --- a/frontend/src/hooks/api/ca/types.ts +++ b/frontend/src/hooks/api/ca/types.ts @@ -66,7 +66,10 @@ export type TUnifiedCertificateAuthority = | TAzureAdCsCertificateAuthority | TInternalCertificateAuthority; -export type TCreateCertificateAuthorityDTO = Omit; +export type TCreateCertificateAuthorityDTO = Omit< + TUnifiedCertificateAuthority, + "id" | "enableDirectIssuance" +>; export type TUpdateCertificateAuthorityDTO = Partial & { id: string; type: CaType; diff --git a/frontend/src/hooks/api/certificateTemplates/mutations.tsx b/frontend/src/hooks/api/certificateTemplates/mutations.tsx index d4647d5ee..0acebae52 100644 --- a/frontend/src/hooks/api/certificateTemplates/mutations.tsx +++ b/frontend/src/hooks/api/certificateTemplates/mutations.tsx @@ -89,7 +89,7 @@ export const useCreateCertTemplateV2 = () => { mutationFn: async (dto) => { const { data } = await apiRequest.post<{ certificateTemplate: TCertificateTemplate; - }>("/api/v1/cert-manager/certificate-templates", dto); + }>("/api/v2/pki/certificate-templates", dto); return data.certificateTemplate; }, onSuccess: (_, { projectId }) => { @@ -108,7 +108,7 @@ export const useUpdateCertTemplateV2 = () => { return useMutation({ mutationFn: async (dto) => { const { data } = await apiRequest.patch<{ certificateTemplate: TCertificateTemplate }>( - `/api/v1/cert-manager/certificate-templates/${dto.templateName}`, + `/api/v2/pki/certificate-templates/${dto.templateName}`, dto ); @@ -130,7 +130,7 @@ export const useDeleteCertTemplateV2 = () => { return useMutation({ mutationFn: async (dto) => { const { data } = await apiRequest.delete<{ certificateTemplate: TCertificateTemplate }>( - `/api/v1/cert-manager/certificate-templates/${dto.templateName}`, + `/api/v2/pki/certificate-templates/${dto.templateName}`, { data: { projectId: dto.projectId diff --git a/frontend/src/hooks/api/certificateTemplates/queries.tsx b/frontend/src/hooks/api/certificateTemplates/queries.tsx index 4b823f296..78c1ebd81 100644 --- a/frontend/src/hooks/api/certificateTemplates/queries.tsx +++ b/frontend/src/hooks/api/certificateTemplates/queries.tsx @@ -57,7 +57,7 @@ export const useListCertificateTemplates = ({ const { data } = await apiRequest.get<{ certificateTemplates: TCertificateTemplateV2[]; totalCount?: number; - }>("/api/v1/pki/certificate-templates", { + }>("/api/v2/pki/certificate-templates", { params: { limit, offset, diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaDetailsSection.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaDetailsSection.tsx index b965d9600..df33f51c8 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaDetailsSection.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaDetailsSection.tsx @@ -152,10 +152,6 @@ export const CaDetailsSection = ({ caId, handlePopUpOpen }: Props) => { : "-"}

-
-

Enable Direct Issuance

-

{ca.enableDirectIssuance ? "True" : "False"}

-
{ca.status === CaStatus.ACTIVE && ( { type: CaType.AZURE_AD_CS, name: "", status: CaStatus.ACTIVE, - enableDirectIssuance: false, configuration: { azureAdcsConnection: { id: "", @@ -184,7 +181,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { type: CaType.ACME, name: "", status: CaStatus.ACTIVE, - enableDirectIssuance: true, configuration: { dnsAppConnection: { id: "", @@ -274,7 +270,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { type: ca.type, name: ca.name, status: ca.status, - enableDirectIssuance: ca.enableDirectIssuance, configuration: { dnsAppConnection: { id: ca.configuration.dnsAppConnectionId, @@ -299,7 +294,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { type: ca.type, name: ca.name, status: ca.status, - enableDirectIssuance: false, configuration: { azureAdcsConnection: { id: ca.configuration.azureAdcsConnectionId, @@ -314,7 +308,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { const onFormSubmit = async ({ type, name, - enableDirectIssuance, status, configuration: formConfiguration }: FormData) => { @@ -346,7 +339,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { name, type, status, - enableDirectIssuance: type === CaType.AZURE_AD_CS ? false : enableDirectIssuance, configuration: configPayload }); } else { @@ -355,7 +347,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { name, type, status, - enableDirectIssuance: type === CaType.AZURE_AD_CS ? false : enableDirectIssuance, configuration: configPayload }); } @@ -648,25 +639,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { name="configuration.azureAdcsConnection" /> )} - {caType === CaType.ACME && ( - { - return ( - - field.onChange(value)} - isChecked={field.value} - > -

Enable Direct Issuance

-
-
- ); - }} - /> - )}