diff --git a/config.example.yaml b/config.example.yaml index a697e1a..6a6e9ff 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -1,11 +1,11 @@ # A list of perspectives with the format . TODO link to pages. perspectives: - - arin.us-east-2 - - arin.us-west-2 - - ripe.eu-central-1 - - ripe.eu-west-2 - - apnic.ap-northeast-2 - - apnic.ap-southeast-1 + - us-east-2 + - us-west-2 + - eu-central-1 + - eu-west-2 + - ap-northeast-2 + - ap-southeast-1 # The AWS region name for the API gateway and controller. api-region: us-east-2 @@ -22,12 +22,3 @@ caa-domains: # absolute maximum regardless of orchestration parameters in request # NOT to be interpreted as the default number of attempts (default is 1 unless explicitly set in request) absolute-max-attempts: 3 - -# Whether to run in a more permissive mode for development. Allows specification of named perspectives. -# False by default. If true, result should NOT be used for production MPIC. -# TODO align on naming and behavior (and where this kind of flag goes... API request or config here). -diagnostic-mode: false - -# Whether to enforce whether two distinct RIR regions must succeed. -# TODO align on whether this flag is valid to even manage. -enforce-distinct-rir-regions: true \ No newline at end of file diff --git a/configure.py b/configure.py index a3be590..f852a64 100755 --- a/configure.py +++ b/configure.py @@ -63,7 +63,7 @@ def main(raw_args=None): if file.endswith(".generated.tf"): os.remove(os.path.join(open_tofu_dir, file)) - regions = [perspective.split('.')[1] for perspective in config['perspectives']] + regions = config['perspectives'] # Generate "main.generated.tf" based on main.tf.template. with open(args.main_tf_template) as stream: @@ -80,8 +80,8 @@ def main(raw_args=None): main_tf_string = main_tf_string.replace("{{perspective-names-list}}", f"\"{perspective_names_list}\"") # Generate the ARNs list for validators. Note that this is not a list of actual ARN values. It is just a list of ARN names that will be substituted by Open Tofu. - arn_validator_list = "|".join([f"${{aws_lambda_function.mpic_dcv_checker_lambda_{region}.arn}}" for region in regions]) - main_tf_string = main_tf_string.replace("{{validator-arns-list}}", f"\"{arn_validator_list}\"") + arn_mpic_dcv_checker_list = "|".join([f"${{aws_lambda_function.mpic_dcv_checker_lambda_{region}.arn}}" for region in regions]) + main_tf_string = main_tf_string.replace("{{validator-arns-list}}", f"\"{arn_mpic_dcv_checker_list}\"") # Generate the ARNs list for CAA resolvers. Note that this is not a list of actual ARN values. It is just a list of ARN names that will be substituted by Open Tofu. arn_mpic_caa_checker_list = "|".join([f"${{aws_lambda_function.mpic_caa_checker_lambda_{region}.arn}}" for region in regions]) @@ -90,14 +90,11 @@ def main(raw_args=None): # Replace default perspective count. main_tf_string = main_tf_string.replace("{{default-perspective-count}}", f"\"{config['default-perspective-count']}\"") - # Replace absolout max attempt count if present. + # Replace absolute max attempt count if present. if "absolute-max-attempts" in config: - main_tf_string = main_tf_string.replace("{{absolut-max-attempts-with-key}}", f"absolute_max_attempts = \"{config['absolute-max-attempts']}\"") + main_tf_string = main_tf_string.replace("{{absolute-max-attempts-with-key}}", f"absolute_max_attempts = \"{config['absolute-max-attempts']}\"") else: - main_tf_string = main_tf_string.replace("{{absolut-max-attempts-with-key}}", "") - - # Replace enforce distinct rir regions. - main_tf_string = main_tf_string.replace("{{enforce-distinct-rir-regions}}", f"\"{1 if config['enforce-distinct-rir-regions'] else 0}\"") + main_tf_string = main_tf_string.replace("{{absolute-max-attempts-with-key}}", "") # Store the secret key for the vantage points hash in an environment variable. hash_secret = ''.join(secrets.choice(string.ascii_letters) for i in range(20)) @@ -133,11 +130,7 @@ def main(raw_args=None): aws_perspective_tf = stream.read() # Iterate through the different regions specified and produce an output file for each region. - for perspective in config['perspectives']: - split_perspective = perspective.split(".") - region = split_perspective[1] - rir_region = split_perspective[0] - + for region in config['perspectives']: aws_perspective_tf_region = aws_perspective_tf.replace("{{region}}", region) # Replace the deployment id. @@ -149,9 +142,6 @@ def main(raw_args=None): # Set the source path for the lambda functions. aws_perspective_tf_region = aws_perspective_tf_region.replace("{{source-path}}", f"{config['source-path']}") - # Set the RIR region to load into env variables. - aws_perspective_tf_region = aws_perspective_tf_region.replace("{{rir-region}}", f"{rir_region}") - if not args.aws_perspective_tf_template.endswith(".tf.template"): print(f"Error: invalid tf template name: {args.aws_perspective_tf_template}. Make sure all tf template files end in '.tf.template'.") exit() diff --git a/open-tofu/aws-perspective.tf.template b/open-tofu/aws-perspective.tf.template index 3c3b3db..8d10260 100644 --- a/open-tofu/aws-perspective.tf.template +++ b/open-tofu/aws-perspective.tf.template @@ -213,11 +213,6 @@ resource "aws_lambda_function" "mpic_dcv_checker_lambda_{{region}}" { layers = [ aws_lambda_layer_version.python311_open_mpic_layer_{{region}}.arn, ] - environment { - variables = { - rir_region = "{{rir-region}}" - } - } vpc_config { subnet_ids = [for s in aws_subnet.subnet_private_{{region}} : s.id] security_group_ids = [for s in aws_default_security_group.default_security_group_{{region}} : s.id] @@ -251,7 +246,6 @@ resource "aws_lambda_function" "mpic_caa_checker_lambda_{{region}}" { environment { variables = { default_caa_domains = {{default-caa-domains}} - rir_region = "{{rir-region}}" } } } \ No newline at end of file diff --git a/open-tofu/main.tf.template b/open-tofu/main.tf.template index e6cbd4e..ae7dbc2 100644 --- a/open-tofu/main.tf.template +++ b/open-tofu/main.tf.template @@ -81,12 +81,11 @@ resource "aws_lambda_function" "mpic_coordinator_lambda" { environment { variables = { perspective_names = {{perspective-names-list}} - validator_arns = {{validator-arns-list}} + dcv_arns = {{validator-arns-list}} caa_arns = {{mpic-caa-checker-arns-list}} default_perspective_count = {{default-perspective-count}} - enforce_distinct_rir_regions = {{enforce-distinct-rir-regions}} hash_secret = {{hash-secret}} - {{absolut-max-attempts-with-key}} + {{absolute-max-attempts-with-key}} } } } diff --git a/pyproject.toml b/pyproject.toml index a2e312e..4658f13 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ dependencies = [ "dnspython==2.6.1", "pydantic==2.8.2", "aws-lambda-powertools[parser]==3.2.0", - "open-mpic-core==2.2.0", + "open-mpic-core==3.0.0", ] [project.optional-dependencies] diff --git a/src/aws_lambda_mpic/__about__.py b/src/aws_lambda_mpic/__about__.py index 3dc1f76..493f741 100644 --- a/src/aws_lambda_mpic/__about__.py +++ b/src/aws_lambda_mpic/__about__.py @@ -1 +1 @@ -__version__ = "0.1.0" +__version__ = "0.3.0" diff --git a/src/aws_lambda_mpic/mpic_caa_checker_lambda/mpic_caa_checker_lambda_function.py b/src/aws_lambda_mpic/mpic_caa_checker_lambda/mpic_caa_checker_lambda_function.py index 1f974ed..3be5ade 100644 --- a/src/aws_lambda_mpic/mpic_caa_checker_lambda/mpic_caa_checker_lambda_function.py +++ b/src/aws_lambda_mpic/mpic_caa_checker_lambda/mpic_caa_checker_lambda_function.py @@ -1,16 +1,15 @@ from aws_lambda_powertools.utilities.parser import event_parser from open_mpic_core.common_domain.check_request import CaaCheckRequest -from open_mpic_core.common_domain.remote_perspective import RemotePerspective from open_mpic_core.mpic_caa_checker.mpic_caa_checker import MpicCaaChecker import os class MpicCaaCheckerLambdaHandler: def __init__(self): - self.perspective = RemotePerspective(rir=os.environ['rir_region'], code=os.environ['AWS_REGION']) + self.perspective_code = os.environ['AWS_REGION'] self.default_caa_domain_list = os.environ['default_caa_domains'].split("|") - self.caa_checker = MpicCaaChecker(self.default_caa_domain_list, self.perspective) + self.caa_checker = MpicCaaChecker(self.default_caa_domain_list, self.perspective_code) def process_invocation(self, caa_request: CaaCheckRequest): caa_response = self.caa_checker.check_caa(caa_request) 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 43bd244..49a2004 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 @@ -10,7 +10,7 @@ from open_mpic_core.mpic_coordinator.messages.mpic_request_validation_messages import MpicRequestValidationMessages from open_mpic_core.mpic_coordinator.mpic_coordinator import MpicCoordinator, MpicCoordinatorConfiguration from open_mpic_core.common_domain.enum.check_type import CheckType -from open_mpic_core.common_domain.remote_perspective import RemotePerspective +from open_mpic_core.mpic_coordinator.domain.remote_perspective import RemotePerspective import boto3 import os @@ -21,10 +21,9 @@ class MpicCoordinatorLambdaHandler: def __init__(self): # load environment variables self.all_target_perspectives = os.environ['perspective_names'].split("|") - self.dcv_arn_list = os.environ['validator_arns'].split("|") # TODO rename to dcv_arns + self.dcv_arn_list = os.environ['dcv_arns'].split("|") self.caa_arn_list = os.environ['caa_arns'].split("|") self.default_perspective_count = int(os.environ['default_perspective_count']) - self.enforce_distinct_rir_regions = int(os.environ['enforce_distinct_rir_regions']) == 1 # TODO may not need... self.global_max_attempts = int(os.environ['absolute_max_attempts']) if 'absolute_max_attempts' in os.environ else None self.hash_secret = os.environ['hash_secret'] @@ -33,7 +32,7 @@ def __init__(self): CheckType.CAA: {self.all_target_perspectives[i]: self.caa_arn_list[i] for i in range(len(self.all_target_perspectives))} } - all_target_perspective_codes = [target_perspective.split('.')[1] for target_perspective in self.all_target_perspectives] + all_target_perspective_codes = self.all_target_perspectives all_possible_perspectives_by_code = MpicCoordinatorLambdaHandler.load_aws_region_config() self.target_perspectives = MpicCoordinatorLambdaHandler.convert_codes_to_remote_perspectives( all_target_perspective_codes, all_possible_perspectives_by_code) @@ -41,7 +40,6 @@ def __init__(self): self.mpic_coordinator_configuration = MpicCoordinatorConfiguration( self.target_perspectives, self.default_perspective_count, - self.enforce_distinct_rir_regions, self.global_max_attempts, self.hash_secret ) @@ -86,7 +84,7 @@ def convert_codes_to_remote_perspectives(perspective_codes: list[str], def call_remote_perspective(self, perspective: RemotePerspective, check_type: CheckType, check_request: BaseCheckRequest) -> CheckResponse: # Uses dcv_arn_list, caa_arn_list client = boto3.client('lambda', perspective.code) - function_name = self.arns_per_perspective_per_check_type[check_type][perspective.rir + "." + perspective.code] + function_name = self.arns_per_perspective_per_check_type[check_type][perspective.code] response = client.invoke( # AWS Lambda-specific structure FunctionName=function_name, InvocationType='RequestResponse', diff --git a/src/aws_lambda_mpic/mpic_dcv_checker_lambda/mpic_dcv_checker_lambda_function.py b/src/aws_lambda_mpic/mpic_dcv_checker_lambda/mpic_dcv_checker_lambda_function.py index 46d1752..faebb3f 100644 --- a/src/aws_lambda_mpic/mpic_dcv_checker_lambda/mpic_dcv_checker_lambda_function.py +++ b/src/aws_lambda_mpic/mpic_dcv_checker_lambda/mpic_dcv_checker_lambda_function.py @@ -1,18 +1,16 @@ from aws_lambda_powertools.utilities.parser import event_parser from open_mpic_core.common_domain.check_request import DcvCheckRequest -from open_mpic_core.common_domain.remote_perspective import RemotePerspective from open_mpic_core.mpic_dcv_checker.mpic_dcv_checker import MpicDcvChecker import os class MpicDcvCheckerLambdaHandler: def __init__(self): - self.perspective = RemotePerspective(rir=os.environ['rir_region'], code=os.environ['AWS_REGION']) - self.dcv_checker = MpicDcvChecker(self.perspective) + self.perspective_code = os.environ['AWS_REGION'] + self.dcv_checker = MpicDcvChecker(self.perspective_code) - def process_invocation(self, dcv_request_dict: dict): - dcv_request = DcvCheckRequest.model_validate(dcv_request_dict) + def process_invocation(self, dcv_request: DcvCheckRequest): dcv_response = self.dcv_checker.check_dcv(dcv_request) status_code = 200 if dcv_response.errors is not None and len(dcv_response.errors) > 0: 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 da4e2fe..4fa0e32 100644 --- a/tests/unit/aws_lambda_mpic/test_mpic_coordinator_lambda.py +++ b/tests/unit/aws_lambda_mpic/test_mpic_coordinator_lambda.py @@ -8,12 +8,12 @@ import yaml from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventModel, APIGatewayEventRequestContext, \ APIGatewayEventIdentity -from pydantic import ValidationError, TypeAdapter +from open_mpic_core.mpic_coordinator.domain.remote_perspective import RemotePerspective +from pydantic import TypeAdapter from open_mpic_core.common_domain.check_request import DcvCheckRequest from open_mpic_core.common_domain.check_response import DcvCheckResponse from open_mpic_core.common_domain.enum.check_type import CheckType -from open_mpic_core.common_domain.remote_perspective import RemotePerspective from open_mpic_core.common_domain.check_response_details import DcvDnsCheckResponseDetails from open_mpic_core.common_domain.enum.dcv_validation_method import DcvValidationMethod from open_mpic_core.mpic_coordinator.domain.mpic_orchestration_parameters import MpicEffectiveOrchestrationParameters @@ -32,11 +32,10 @@ class TestMpicCoordinatorLambda: @pytest.fixture(scope='class') def set_env_variables(): envvars = { - 'perspective_names': 'arin.us-east-1|arin.us-west-1|ripe.eu-west-2|ripe.eu-central-2|apnic.ap-northeast-1|apnic.ap-south-2', - 'validator_arns': 'arn:aws:acm-pca:us-east-1:123456789012:validator/arin.us-east-1|arn:aws:acm-pca:us-west-1:123456789012:validator/arin.us-west-1|arn:aws:acm-pca:eu-west-2:123456789012:validator/ripe.eu-west-2|arn:aws:acm-pca:eu-central-2:123456789012:validator/ripe.eu-central-2|arn:aws:acm-pca:ap-northeast-1:123456789012:validator/apnic.ap-northeast-1|arn:aws:acm-pca:ap-south-2:123456789012:validator/apnic.ap-south-2', - 'caa_arns': 'arn:aws:acm-pca:us-east-1:123456789012:caa/arin.us-east-1|arn:aws:acm-pca:us-west-1:123456789012:caa/arin.us-west-1|arn:aws:acm-pca:eu-west-2:123456789012:caa/ripe.eu-west-2|arn:aws:acm-pca:eu-central-2:123456789012:caa/ripe.eu-central-2|arn:aws:acm-pca:ap-northeast-1:123456789012:caa/apnic.ap-northeast-1|arn:aws:acm-pca:ap-south-2:123456789012:caa/apnic.ap-south-2', + 'perspective_names': 'us-east-1|us-west-1|eu-west-2|eu-central-2|ap-northeast-1|ap-south-2', + 'dcv_arns': 'arn:aws:acm-pca:us-east-1:123456789012:validator/us-east-1|arn:aws:acm-pca:us-west-1:123456789012:validator/us-west-1|arn:aws:acm-pca:eu-west-2:123456789012:validator/eu-west-2|arn:aws:acm-pca:eu-central-2:123456789012:validator/eu-central-2|arn:aws:acm-pca:ap-northeast-1:123456789012:validator/ap-northeast-1|arn:aws:acm-pca:ap-south-2:123456789012:validator/ap-south-2', + 'caa_arns': 'arn:aws:acm-pca:us-east-1:123456789012:caa/us-east-1|arn:aws:acm-pca:us-west-1:123456789012:caa/us-west-1|arn:aws:acm-pca:eu-west-2:123456789012:caa/eu-west-2|arn:aws:acm-pca:eu-central-2:123456789012:caa/eu-central-2|arn:aws:acm-pca:ap-northeast-1:123456789012:caa/ap-northeast-1|arn:aws:acm-pca:ap-south-2:123456789012:caa/ap-south-2', 'default_perspective_count': '3', - 'enforce_distinct_rir_regions': '1', # TODO may not need this... 'hash_secret': 'test_secret' } with pytest.MonkeyPatch.context() as class_scoped_monkeypatch: