From 37fd3a813fa8000372be93a62c6f4db7eeaa171e Mon Sep 17 00:00:00 2001 From: Dmitry Sharkov Date: Wed, 11 Feb 2026 10:17:28 -0500 Subject: [PATCH 1/6] updated open-mpic-core to v6.3.1 to pull in persistent dns bugfixes --- pyproject.toml | 2 +- src/aws_lambda_mpic/__about__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 10ce134..81b9f98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ dependencies = [ "pydantic==2.11.7", "aiohttp==3.13.3", "aws-lambda-powertools[parser]==3.15.1", - "open-mpic-core==6.3.0", + "open-mpic-core==6.3.1", "aioboto3~=14.3.0", "black==25.1.0", ] diff --git a/src/aws_lambda_mpic/__about__.py b/src/aws_lambda_mpic/__about__.py index 14d9d2f..3c1e9cb 100644 --- a/src/aws_lambda_mpic/__about__.py +++ b/src/aws_lambda_mpic/__about__.py @@ -1 +1 @@ -__version__ = "1.7.0" +__version__ = "1.7.1" From c8db1133a57d470615ff055d0c6708020257061a Mon Sep 17 00:00:00 2001 From: Dmitry Sharkov Date: Wed, 11 Feb 2026 14:44:31 -0500 Subject: [PATCH 2/6] updated core version to pull in new crypto library to address CVE --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 81b9f98..545a7fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ dependencies = [ "pydantic==2.11.7", "aiohttp==3.13.3", "aws-lambda-powertools[parser]==3.15.1", - "open-mpic-core==6.3.1", + "open-mpic-core==6.3.2", "aioboto3~=14.3.0", "black==25.1.0", ] From 2f387e58291765b49ee7c47cf355b158a599ee70 Mon Sep 17 00:00:00 2001 From: Dmitry Sharkov Date: Fri, 13 Mar 2026 19:34:40 -0400 Subject: [PATCH 3/6] updated open-mpic-core to v6.3.3 to pull in removal of black library from deployed artifact. updated toml here to match that change as well. --- pyproject.toml | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 545a7fb..0d6687d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,12 +33,14 @@ dependencies = [ "pydantic==2.11.7", "aiohttp==3.13.3", "aws-lambda-powertools[parser]==3.15.1", - "open-mpic-core==6.3.2", + "open-mpic-core==6.3.3", "aioboto3~=14.3.0", - "black==25.1.0", ] [project.optional-dependencies] +dev = [ + "black==26.3.0" +] test = [ "pytest==8.4.1", "pytest-cov==6.2.1", @@ -68,12 +70,24 @@ build.targets.wheel.packages = ["src/aws_lambda_mpic"] skip-install = false type="virtual" path="venv" +features = [ + "dev", + "test", +] +installer = "pip" [tool.hatch.envs.default.env-vars] PIP_INDEX_URL = "https://pypi.org/simple/" #PIP_EXTRA_INDEX_URL = "https://test.pypi.org/simple/" # FIXME here temporarily to test open-mpic-core packaging PIP_VERBOSE = "1" +[tool.hatch.envs.default.scripts] +pre-install = "python -m ensurepip" +unit = "pytest" +unit-html = "pytest --html=testreports/index.html" # generate html report (warning: uses an aging plugin, 11-2023) +integration = "pytest tests/integration" +coverage = "pytest --cov=src/aws_lambda_mpic --cov-report=term-missing --cov-report=html" + [tool.hatch.envs.lambda] skip-install = true python = "3.11" @@ -112,24 +126,15 @@ deploy-no-dnssec = [ "apply-tf-no-dnssec" ] +[tool.hatch.envs.dev] +template = "default" [tool.hatch.envs.test] -skip-install = false -features = [ - "test", -] -installer = "pip" +template = "default" #[tool.hatch.envs.test.env-vars] #PIP_EXTRA_INDEX_URL = "https://test.pypi.org/simple/" -[tool.hatch.envs.test.scripts] -pre-install = "python -m ensurepip" -unit = "pytest" -unit-html = "pytest --html=testreports/index.html" # generate html report (warning: uses an aging plugin, 11-2023) -integration = "pytest tests/integration" -coverage = "pytest --cov=src/aws_lambda_mpic --cov-report=term-missing --cov-report=html" - [tool.hatch.envs.hatch-test] default-args = ["tests/unit"] randomize = true From 6966336e04bd9094f6b2dc0fcb551040ed58184b Mon Sep 17 00:00:00 2001 From: Dmitry Sharkov Date: Fri, 13 Mar 2026 19:38:27 -0400 Subject: [PATCH 4/6] ran latest black formatter and updated formatting in several files --- .../mpic_coordinator_lambda_function.py | 2 +- tests/integration/test_deployed_mpic_api.py | 12 +++---- .../test_dcv_checker_lambda.py | 2 +- .../test_mpic_coordinator_lambda.py | 31 ++++++++++++------- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/aws_lambda_mpic/mpic_coordinator_lambda/mpic_coordinator_lambda_function.py b/src/aws_lambda_mpic/mpic_coordinator_lambda/mpic_coordinator_lambda_function.py index f05cd93..11624eb 100644 --- a/src/aws_lambda_mpic/mpic_coordinator_lambda/mpic_coordinator_lambda_function.py +++ b/src/aws_lambda_mpic/mpic_coordinator_lambda/mpic_coordinator_lambda_function.py @@ -128,7 +128,7 @@ async def call_remote_perspective( Payload=check_request.model_dump_json(), # AWS Lambda functions expect a JSON string for payload ) response_payload = await response["Payload"].read() - if 'FunctionError' in response: + if "FunctionError" in response: raise LambdaExecutionException(f"Lambda execution error: {response_payload.decode('utf-8')}") response_payload = json.loads(response_payload) return self.check_response_adapter.validate_json(response_payload["body"]) diff --git a/tests/integration/test_deployed_mpic_api.py b/tests/integration/test_deployed_mpic_api.py index dcf298a..fd73432 100644 --- a/tests/integration/test_deployed_mpic_api.py +++ b/tests/integration/test_deployed_mpic_api.py @@ -18,7 +18,6 @@ import testing_api_client - MPIC_REQUEST_PATH = "/mpic" @@ -61,8 +60,9 @@ def api_should_return_200_and_passed_corroboration_given_successful_caa_check(se # assert response body has a list of perspectives with length 2, and each element has response code 200 perspectives_list: list[PerspectiveResponse] = mpic_response.perspectives assert len(perspectives_list) == request.orchestration_parameters.perspective_count + assert ( - len(list(filter(lambda perspective: perspective.check_response.check_type == CheckType.CAA, perspectives_list))) + len(list(filter(lambda p: p.check_response.check_type == CheckType.CAA, perspectives_list))) == request.orchestration_parameters.perspective_count ) @@ -109,9 +109,7 @@ def api_should_return_is_valid_false_for_all_tests_in_do_not_issue_caa_test_suit mpic_response = self.mpic_response_adapter.validate_json(response.text) assert mpic_response.is_valid is False - def api_should_return_is_valid_true_for_caa_lookup_failure_if_allow_lookup_failure_flag_is_true( - self, api_client - ): + def api_should_return_is_valid_true_for_caa_lookup_failure_if_allow_lookup_failure_flag_is_true(self, api_client): request = MpicCaaRequest( domain_or_ip_target="servfail.caatestsuite-dnssec.com", orchestration_parameters=MpicRequestOrchestrationParameters(perspective_count=3, quorum_count=2), @@ -258,7 +256,7 @@ def api_should_return_200_given_valid_http_01_validation( request = MpicDcvRequest( domain_or_ip_target=domain_or_ip_target, orchestration_parameters=MpicRequestOrchestrationParameters(perspective_count=3, quorum_count=2), - dcv_check_parameters=DcvAcmeHttp01ValidationParameters(key_authorization=key_authorization, token=token) + dcv_check_parameters=DcvAcmeHttp01ValidationParameters(key_authorization=key_authorization, token=token), ) 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())) @@ -358,7 +356,7 @@ def api_should_return_200_is_valid_true_given_valid_dns_change_validation( def api_should_return_200_and_failed_corroboration_given_failed_dcv_check(self, api_client): request = MpicDcvRequest( domain_or_ip_target="ifconfig.me", - dcv_check_parameters=DcvWebsiteChangeValidationParameters(http_token_path="/", challenge_value="test") + dcv_check_parameters=DcvWebsiteChangeValidationParameters(http_token_path="/", challenge_value="test"), ) print("\nRequest:\n", json.dumps(request.model_dump(), indent=4)) # pretty print request body diff --git a/tests/unit/aws_lambda_mpic/test_dcv_checker_lambda.py b/tests/unit/aws_lambda_mpic/test_dcv_checker_lambda.py index c423ce2..934cb0b 100644 --- a/tests/unit/aws_lambda_mpic/test_dcv_checker_lambda.py +++ b/tests/unit/aws_lambda_mpic/test_dcv_checker_lambda.py @@ -55,7 +55,7 @@ def lambda_handler__should_return_appropriate_status_code_given_errors_in_respon ): mock_dcv_response = TestDcvCheckerLambda.create_dcv_check_response() mock_dcv_response.check_passed = False - mock_dcv_response.errors = [(MpicValidationError(error_type=error_type, error_message=error_message))] + mock_dcv_response.errors = [MpicValidationError(error_type=error_type, error_message=error_message)] mock_return_value = { "statusCode": expected_status_code, "headers": {"Content-Type": "application/json"}, diff --git a/tests/unit/aws_lambda_mpic/test_mpic_coordinator_lambda.py b/tests/unit/aws_lambda_mpic/test_mpic_coordinator_lambda.py index db7b2f4..3ef2b66 100644 --- a/tests/unit/aws_lambda_mpic/test_mpic_coordinator_lambda.py +++ b/tests/unit/aws_lambda_mpic/test_mpic_coordinator_lambda.py @@ -12,6 +12,7 @@ APIGatewayEventRequestContext, APIGatewayEventIdentity, ) +from open_mpic_core.common_domain.enum.regional_internet_registry import RegionalInternetRegistry from pydantic import TypeAdapter, BaseModel from open_mpic_core import RemotePerspective @@ -80,13 +81,17 @@ def set_env_variables(): def call_remote_perspective__should_make_aws_lambda_call_with_provided_arguments_and_return_check_response( self, set_env_variables, mocker ): - lambda_handler, mock_client = self.mock_lambda_handler_for_lambda_invoke(mocker, self.create_successful_aioboto3_response_for_dcv_check) + lambda_handler, mock_client = self.mock_lambda_handler_for_lambda_invoke( + mocker, self.create_successful_aioboto3_response_for_dcv_check + ) dcv_check_request = ValidCheckCreator.create_valid_dns_check_request() perspective_code = "us-west-1" - check_response = asyncio.get_event_loop().run_until_complete(lambda_handler.call_remote_perspective( - RemotePerspective(code=perspective_code, rir="arin"), CheckType.DCV, dcv_check_request - )) + check_response = asyncio.get_event_loop().run_until_complete( + lambda_handler.call_remote_perspective( + RemotePerspective(code=perspective_code, rir="arin"), CheckType.DCV, dcv_check_request + ) + ) assert check_response.check_passed is True # hijacking the value of 'details.found_at' to verify that the right arguments got passed to the call assert check_response.details.found_at == dcv_check_request.domain_or_ip_target @@ -103,16 +108,20 @@ def call_remote_perspective__should_make_aws_lambda_call_with_provided_arguments def call_remote_perspective__should_make_aws_lambda_call_and_handle_lambda_execution_exceptions( self, set_env_variables, mocker ): - lambda_handler, mock_client = self.mock_lambda_handler_for_lambda_invoke(mocker, self.create_error_aioboto3_response) + lambda_handler, mock_client = self.mock_lambda_handler_for_lambda_invoke( + mocker, self.create_error_aioboto3_response + ) class Dummy(BaseModel): pass with pytest.raises(LambdaExecutionException) as exc_info: - asyncio.get_event_loop().run_until_complete(lambda_handler.call_remote_perspective( - RemotePerspective(code="us-west-1", rir="arin"), CheckType.DCV, Dummy() - )) - assert exc_info.value.args[0] == "Lambda execution error: {\"errorMessage\": \"some message\"}" + asyncio.get_event_loop().run_until_complete( + lambda_handler.call_remote_perspective( + RemotePerspective(code="us-west-1", rir=RegionalInternetRegistry.ARIN), CheckType.DCV, Dummy() + ) + ) + assert exc_info.value.args[0] == 'Lambda execution error: {"errorMessage": "some message"}' def lambda_handler__should_return_400_error_and_details_given_invalid_request_body(self): request = ValidMpicRequestCreator.create_valid_dcv_mpic_request() @@ -253,7 +262,7 @@ async def read(self): return json_bytes return {"Payload": MockStreamingBody()} - + # noinspection PyUnusedLocal async def create_error_aioboto3_response(self, *args, **kwargs): expected_response = {"errorMessage": "some message"} @@ -263,7 +272,7 @@ class MockStreamingBody: # noinspection PyMethodMayBeStatic async def read(self): return json_bytes - + # See https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda/client/invoke.html, "Response Structure" return {"Payload": MockStreamingBody(), "FunctionError": None} From 6345cf6d738c281d57f057eb0db80a71fe00949f Mon Sep 17 00:00:00 2001 From: Dmitry Sharkov Date: Wed, 8 Apr 2026 10:40:25 -0400 Subject: [PATCH 5/6] incorporated 6.4.0 of open-mpic-core, which introduces require_exact_case flag for Website Change and DNS TXT change (non-ACME) DCV methods. --- pyproject.toml | 8 ++++---- src/aws_lambda_mpic/__about__.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0d6687d..28e330f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,12 +28,12 @@ classifiers = [ dependencies = [ #"open-mpic-core @ git+https://github.com/open-mpic/open-mpic-core-python.git@birgelee-version-bump", "pyyaml==6.0.2", - "requests==2.32.4", + "requests==2.33.0", "dnspython==2.7.0", "pydantic==2.11.7", - "aiohttp==3.13.3", + "aiohttp==3.13.4", "aws-lambda-powertools[parser]==3.15.1", - "open-mpic-core==6.3.3", + "open-mpic-core==6.4.0", "aioboto3~=14.3.0", ] @@ -58,7 +58,7 @@ Source = "https://github.com/open-mpic/aws-lambda-python" #virtual = ".hatch" [tool.api] -spec_version = "3.8.0" +spec_version = "3.9.0" spec_repository = "https://github.com/open-mpic/open-mpic-specification" [tool.hatch] diff --git a/src/aws_lambda_mpic/__about__.py b/src/aws_lambda_mpic/__about__.py index 3c1e9cb..29654ee 100644 --- a/src/aws_lambda_mpic/__about__.py +++ b/src/aws_lambda_mpic/__about__.py @@ -1 +1 @@ -__version__ = "1.7.1" +__version__ = "1.8.0" From 57e05a3306713d54a3e2369b6b3dd9db8576210d Mon Sep 17 00:00:00 2001 From: Henry Birge-Lee Date: Wed, 8 Apr 2026 22:59:25 -0400 Subject: [PATCH 6/6] Update README.md to spec 3.9.0 link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 26abc35..47afe1c 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ The above sample must be run from the root directory of a deployed Open MPIC aws The API is compliant with the [Open MPIC Specification](https://github.com/open-mpic/open-mpic-specification). -There is [documentation based on the API specification used in this version](https://open-mpic.org/documentation.html?commit=149f38323babe01f0865565ae8a9a4deb0de8ec0). +There is [documentation based on the API specification used in this version](https://open-mpic.org/documentation.html?commit=371feaaed467a23089ef9b867d50649c345238e9). ## Development Code changes can easily be deployed by editing the .py files and then rezipping the project via `./zip-all.sh` and `./2-package.sh` in the `layer` directory. Then, running `tofu apply` run from the open-tofu directory will update only on the required resources and leave the others unchanged. If any `.tf.template` files are changed or `config.yaml` is edited, `hatch run ./configure.py` must be rerun followed by `tofu apply` in the open-tofu directory.