From a0571002743f0549e68322f70eefeecae6ea978e Mon Sep 17 00:00:00 2001 From: Fang-Pen Lin Date: Thu, 6 Nov 2025 22:54:52 -0800 Subject: [PATCH] More test cases --- .../features/pki/acme/access-control.feature | 91 ++++++++++++++++++- backend/bdd/features/pki/acme/account.feature | 10 +- backend/bdd/features/pki/acme/auth.feature | 2 +- .../features/pki/acme/cert-profile.feature | 2 +- .../bdd/features/pki/acme/challenge.feature | 2 +- backend/bdd/features/pki/acme/nonce.feature | 4 +- backend/bdd/features/pki/acme/order.feature | 12 +-- backend/bdd/features/steps/pki_acme.py | 33 ++++--- 8 files changed, 124 insertions(+), 32 deletions(-) diff --git a/backend/bdd/features/pki/acme/access-control.feature b/backend/bdd/features/pki/acme/access-control.feature index f39d087a3..96da3f7c8 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 across 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/pki/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/pki/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 "" @@ -62,7 +62,87 @@ Feature: Access Control Scenario Outline: Access resources across a different profile 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/pki/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 + Then I add names to certificate signing request csr + """ + { + "COMMON_NAME": "localhost" + } + """ + Then I create a RSA private key pair as cert_key + Then I sign the certificate signing request csr with private key cert_key and output it as csr_pem in PEM format + Then I submit the certificate signing request PEM csr_pem certificate order to the ACME server as order + Then I peak and memorize the next nonce as nonce + Then I memorize with jq "" as + When I send a raw ACME request to "" + """ + { + "protected": { + "alg": "RS256", + "nonce": "{nonce}", + "url": "", + "kid": "{acme_account0.uri}" + }, + "payload": {"invalid": "payload"} + } + """ + # With original owner account under their profile, the invalid payload is going to trigger other errors instead of + # 404, this is to make sure that our URLs are actually correct + Then the value response.status_code should not be equal to 404 + And I put away current ACME client as client0 + + 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 + """ + { + "projectId": "{PROJECT_ID}", + "slug": "{profile_slug}", + "description": "", + "enrollmentType": "acme", + "caId": "{CERT_CA_ID}", + "certificateTemplateId": "{CERT_TEMPLATE_ID}", + "acmeConfig": {} + } + """ + 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" + 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" + 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 + When I send a raw ACME request to "" + """ + { + "protected": { + "alg": "RS256", + "nonce": "{nonce}", + "url": "", + "kid": "{acme_account1.uri}" + }, + "raw_payload": "" + } + """ + Then the value response.status_code should be equal to 404 + + 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 | {order.uri} | | + | order | . | not_used | {order.uri}/finalize | {\"csr\": \"\"} | + | 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: 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" 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 @@ -99,7 +179,7 @@ Feature: Access Control When I send a "GET" request to "/api/v1/pki/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/pki/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 @@ -126,9 +206,10 @@ Feature: Access Control | order | .authorizations[0].uri | auth_uri | {auth_uri} | | | order | .authorizations[0].body.challenges[0].url | challenge_uri | {challenge_uri} | {} | + 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/pki/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 diff --git a/backend/bdd/features/pki/acme/account.feature b/backend/bdd/features/pki/acme/account.feature index 2c0ce3566..589c5ab24 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/pki/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/(.+) 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/pki/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 acme_account @@ -16,13 +16,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/pki/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/pki/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 "" @@ -38,7 +38,7 @@ 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/pki/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" diff --git a/backend/bdd/features/pki/acme/auth.feature b/backend/bdd/features/pki/acme/auth.feature index 65b8ec114..46cc9d4e2 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/pki/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/cert-profile.feature b/backend/bdd/features/pki/acme/cert-profile.feature index 92a921dde..3c292e8ba 100644 --- a/backend/bdd/features/pki/acme/cert-profile.feature +++ b/backend/bdd/features/pki/acme/cert-profile.feature @@ -45,5 +45,5 @@ Feature: ACME Cert Profile 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/pki/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 b36a3e328..bee46c3fb 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/pki/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 601c53a85..9a55ae284 100644 --- a/backend/bdd/features/pki/acme/nonce.feature +++ b/backend/bdd/features/pki/acme/nonce.feature @@ -8,7 +8,7 @@ Feature: Nonce 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/pki/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 @@ -51,7 +51,7 @@ Feature: Nonce 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/pki/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 diff --git a/backend/bdd/features/pki/acme/order.feature b/backend/bdd/features/pki/acme/order.feature index 9e8b47980..19f467f00 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/pki/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 @@ -22,7 +22,7 @@ Feature: Order 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/pki/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/pki/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 @@ -72,7 +72,7 @@ Feature: Order 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/pki/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" @@ -105,7 +105,7 @@ 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/pki/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" @@ -129,7 +129,7 @@ Feature: Order And the value response with jq ".status" should be equal to 400 And the value response with jq ".type" should be equal to "urn:ietf:params:acme:error:unsupportedIdentifier" And the value response with jq ".detail" should be equal to "Invalid DNS identifier" - + Examples: Bad Identifier Vluaes | identifier_value | | 127.0.0.1 | diff --git a/backend/bdd/features/steps/pki_acme.py b/backend/bdd/features/steps/pki_acme.py index 88c31c4a0..1d20cd9bd 100644 --- a/backend/bdd/features/steps/pki_acme.py +++ b/backend/bdd/features/steps/pki_acme.py @@ -191,23 +191,34 @@ def step_impl(context: Context, method: str, url: str): logger.debug("Response JSON payload: %r", response.json()) -@when("I have an ACME client connecting to {url}") -def step_impl(context: Context, url: str): - private_key = rsa.generate_private_key( - public_exponent=ACC_KEY_PUBLIC_EXPONENT, key_size=ACC_KEY_BITS - ) - pem_bytes = private_key.private_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PrivateFormat.PKCS8, - encryption_algorithm=serialization.NoEncryption(), - ) - acc_jwk = JWKRSA.load(pem_bytes) +def create_acme_client(context: Context, url: str, acc_jwk: JWKRSA | None = None): + if acc_jwk is None: + private_key = rsa.generate_private_key( + public_exponent=ACC_KEY_PUBLIC_EXPONENT, key_size=ACC_KEY_BITS + ) + pem_bytes = private_key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.PKCS8, + encryption_algorithm=serialization.NoEncryption(), + ) + acc_jwk = JWKRSA.load(pem_bytes) net = client.ClientNetwork(acc_jwk) directory_url = url.format(**context.vars) directory = client.ClientV2.get_directory(directory_url, net) context.acme_client = client.ClientV2(directory, net=net) +@when('I have an ACME client connecting to "{url}"') +def step_impl(context: Context, url: str): + create_acme_client(context, url) + + +@when('I have an ACME client connecting to "{url}" with the key pair from {client_var}') +def step_impl(context: Context, url: str, client_var: str): + another_client = eval_var(context, client_var, as_json=False) + create_acme_client(context, url, acc_jwk=another_client.net.key) + + @then('the response status code should be "{expected_status_code:d}"') def step_impl(context: Context, expected_status_code: int): assert context.vars["response"].status_code == expected_status_code, (