From d15539050a2f0be3e8af4e7c970ce1019690262c Mon Sep 17 00:00:00 2001 From: Henry Birge-Lee Date: Fri, 3 Jan 2025 16:32:13 -0500 Subject: [PATCH 1/3] dns-01 integration tests --- tests/integration/test_deployed_mpic_api.py | 43 ++++++++++++++++----- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/tests/integration/test_deployed_mpic_api.py b/tests/integration/test_deployed_mpic_api.py index 42777cf..8e19c62 100644 --- a/tests/integration/test_deployed_mpic_api.py +++ b/tests/integration/test_deployed_mpic_api.py @@ -3,7 +3,7 @@ import pytest from pydantic import TypeAdapter -from open_mpic_core.common_domain.check_parameters import CaaCheckParameters, DcvWebsiteChangeValidationDetails +from open_mpic_core.common_domain.check_parameters import CaaCheckParameters, DcvWebsiteChangeValidationDetails, DcvAcmeDns01ValidationDetails from open_mpic_core.common_domain.check_parameters import DcvCheckParameters from open_mpic_core.common_domain.enum.certificate_type import CertificateType from open_mpic_core.common_domain.enum.check_type import CheckType @@ -141,23 +141,48 @@ def api_should_return_is_valid_false_for_do_not_issue_caa_test_suite_for_rfc_684 mpic_response = self.mpic_response_adapter.validate_json(response.text) assert mpic_response.is_valid is False - @pytest.mark.skip(reason='Not implemented yet') - def api_should_return_200_given_valid_dcv_validation(self, api_client): + @pytest.mark.parametrize('domain_or_ip_target, purpose_of_test', [ + ('dns-01.integration-testing.open-mpic.org', 'Standard proper dns-01 test'), + ('dns-01-multi.integration-testing.open-mpic.org', 'Proper dns-01 test with multiple TXT records'), + ('dns-01-cname.integration-testing.open-mpic.org', 'Proper dns-01 test with CNAME') + ]) + def api_should_return_200_given_valid_dns_01_validation(self, api_client, domain_or_ip_target, purpose_of_test): + print(f"Running test for {domain_or_ip_target} ({purpose_of_test})") request = MpicDcvRequest( - domain_or_ip_target='example.com', + domain_or_ip_target=domain_or_ip_target, orchestration_parameters=MpicRequestOrchestrationParameters(perspective_count=3, quorum_count=2), dcv_check_parameters=DcvCheckParameters( - validation_details=DcvWebsiteChangeValidationDetails(http_token_path='/', - challenge_value='test') + validation_details=DcvAcmeDns01ValidationDetails(key_authorization="7FwkJPsKf-TH54wu4eiIFA3nhzYaevsL7953ihy-tpo") ) ) print("\nRequest:\n", json.dumps(request.model_dump(), indent=4)) # pretty print request body response = api_client.post(MPIC_REQUEST_PATH, json.dumps(request.model_dump())) assert response.status_code == 200 - response_body = json.loads(response.text) - print("\nResponse:\n", json.dumps(response_body, indent=4)) # pretty print response body - # finish test... (and figure out how to actually run it successfully and reliably) + mpic_response = self.mpic_response_adapter.validate_json(response.text) + + assert mpic_response.is_valid is True + + @pytest.mark.parametrize('domain_or_ip_target, purpose_of_test', [ + ('dns-01-leading-whitespace.integration-testing.open-mpic.org', 'leading whitespace'), + ('dns-01-trailing-whitespace.integration-testing.open-mpic.org', 'trailing'), + ('dns-01-nxdomain.integration-testing.open-mpic.org', 'NXDOMAIN') + ]) + def api_should_return_200_is_valid_false_given_invalid_dns_01_validation(self, api_client, domain_or_ip_target, purpose_of_test): + request = MpicDcvRequest( + domain_or_ip_target=domain_or_ip_target, + orchestration_parameters=MpicRequestOrchestrationParameters(perspective_count=3, quorum_count=2), + dcv_check_parameters=DcvCheckParameters( + validation_details=DcvAcmeDns01ValidationDetails(key_authorization="7FwkJPsKf-TH54wu4eiIFA3nhzYaevsL7953ihy-tpo") + ) + ) + + print("\nRequest:\n", json.dumps(request.model_dump(), indent=4)) # pretty print request body + response = api_client.post(MPIC_REQUEST_PATH, json.dumps(request.model_dump())) + assert response.status_code == 200 + mpic_response = self.mpic_response_adapter.validate_json(response.text) + + assert mpic_response.is_valid is False def api_should_return_200_and_failed_corroboration_given_failed_dcv_check(self, api_client): request = MpicDcvRequest( From 340b5829ff5f699303f6da30a60676837a442f2f Mon Sep 17 00:00:00 2001 From: Henry Birge-Lee Date: Fri, 3 Jan 2025 23:13:30 -0500 Subject: [PATCH 2/3] added dns change tests --- tests/integration/test_deployed_mpic_api.py | 28 ++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_deployed_mpic_api.py b/tests/integration/test_deployed_mpic_api.py index 8e19c62..653febd 100644 --- a/tests/integration/test_deployed_mpic_api.py +++ b/tests/integration/test_deployed_mpic_api.py @@ -3,10 +3,11 @@ import pytest from pydantic import TypeAdapter -from open_mpic_core.common_domain.check_parameters import CaaCheckParameters, DcvWebsiteChangeValidationDetails, DcvAcmeDns01ValidationDetails +from open_mpic_core.common_domain.check_parameters import CaaCheckParameters, DcvWebsiteChangeValidationDetails, DcvAcmeDns01ValidationDetails, DcvDnsChangeValidationDetails from open_mpic_core.common_domain.check_parameters import DcvCheckParameters from open_mpic_core.common_domain.enum.certificate_type import CertificateType from open_mpic_core.common_domain.enum.check_type import CheckType +from open_mpic_core.common_domain.enum.dns_record_type import DnsRecordType from open_mpic_core.mpic_coordinator.domain.mpic_request import MpicCaaRequest from open_mpic_core.mpic_coordinator.domain.mpic_request import MpicDcvRequest from open_mpic_core.mpic_coordinator.domain.mpic_orchestration_parameters import MpicRequestOrchestrationParameters @@ -169,6 +170,7 @@ def api_should_return_200_given_valid_dns_01_validation(self, api_client, domain ('dns-01-nxdomain.integration-testing.open-mpic.org', 'NXDOMAIN') ]) def api_should_return_200_is_valid_false_given_invalid_dns_01_validation(self, api_client, domain_or_ip_target, purpose_of_test): + print(f"Running test for {domain_or_ip_target} ({purpose_of_test})") request = MpicDcvRequest( domain_or_ip_target=domain_or_ip_target, orchestration_parameters=MpicRequestOrchestrationParameters(perspective_count=3, quorum_count=2), @@ -184,6 +186,30 @@ def api_should_return_200_is_valid_false_given_invalid_dns_01_validation(self, a assert mpic_response.is_valid is False + @pytest.mark.parametrize('domain_or_ip_target, dns_record_type, challenge_value, purpose_of_test', [ + ('dns-change-txt.integration-testing.open-mpic.org', DnsRecordType.TXT, "1234567890abcdefg.", 'standard TXT dns change'), + ('dns-change-cname.integration-testing.open-mpic.org', DnsRecordType.CNAME, "1234567890abcdefg.", 'standard CNAME dns change'), + ('dns-change-caa.integration-testing.open-mpic.org', DnsRecordType.CAA, '0 dnschange "1234567890abcdefg."', 'standard CAA dns change'), + ]) + def api_should_return_200_is_valid_true_given_valid_dns_change_validation(self, api_client, domain_or_ip_target, dns_record_type, challenge_value, purpose_of_test): + print(f"Running test for {domain_or_ip_target} ({purpose_of_test})") + request = MpicDcvRequest( + domain_or_ip_target=domain_or_ip_target, + orchestration_parameters=MpicRequestOrchestrationParameters(perspective_count=3, quorum_count=2), + dcv_check_parameters=DcvCheckParameters( + validation_details=DcvDnsChangeValidationDetails(challenge_value=challenge_value, dns_record_type=dns_record_type, dns_name_prefix="") + ) + ) + + print("\nRequest:\n", json.dumps(request.model_dump(), indent=4)) # pretty print request body + response = api_client.post(MPIC_REQUEST_PATH, json.dumps(request.model_dump())) + assert response.status_code == 200 + print("\nResponse:\n", json.dumps(json.loads(response.text), indent=4)) # pretty print request body + + mpic_response = self.mpic_response_adapter.validate_json(response.text) + + assert mpic_response.is_valid is True + def api_should_return_200_and_failed_corroboration_given_failed_dcv_check(self, api_client): request = MpicDcvRequest( domain_or_ip_target='ifconfig.me', From bb0874371fc01d95e89f6df9b06f21e78dfc86df Mon Sep 17 00:00:00 2001 From: Henry Birge-Lee Date: Sun, 5 Jan 2025 23:07:04 -0500 Subject: [PATCH 3/3] new readme to indicate integration availability --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 15a7c30..dffd2db 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,8 @@ hatch run test:integration ``` Note: integration tests cannot currently be invoked by running `pytest tests/integration` because `PYTHONPATH` is not set correctly in that case. +The integration tests test a live, deployed API and point the API at real web resources that are provisioned for testing purposes. The integration test content is currently hosted on `caatestsuite.com` (maintained by SSLMate) and `integration-testing.open-mpic.org` (maintained by the maintainers of the Open MPIC project). The zone file for `caatestsuite.com` can be found [here](https://github.com/SSLMate/caatestsuite) along with more info about the tests at [caatestsuite.com](https://caatestsuite.com), and the zone file for `integration-testing.open-mpic.org` can be found [here](https://github.com/open-mpic/open-mpic-integration-zone). Both of these services are maintained on a best-effort basis. If there is an issue with integration tests, check the availability of these two services and the responses from the sub-domains used in the integration tests. THESE SERVICES ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. They are not intended for use outside of development integration testing (i.e., no excessive query volume, no use in production systems). + If you encounter issues running integration tests with the above commands, contact the project maintainers. @@ -93,9 +95,8 @@ After `tofu destroy`, `./clean.sh` in the root directory also clears generated/z # Remaining tasks -The Open MPIC project is currently under development. The pre-alpha release includes support for the HTTP and DNS domain validation methods using Amazon Web Services Lambda and API Gateway. The work items remaining to a feature-complete production-level product include the following: (subject to change) +The Open MPIC project is currently under development. The work items remaining to a feature-complete production-level product include the following: (subject to change) -- Full alighnment with API spec v2 - Additional integration testing Throughout the development process, we will address any GitHub issues raised, and may modify the API accordingly. We also welcome pull requests from the general community.