diff --git a/src/cfnlint/rules/formats/SubnetId.py b/src/cfnlint/rules/formats/SubnetId.py new file mode 100644 index 0000000000..f4e5311cf2 --- /dev/null +++ b/src/cfnlint/rules/formats/SubnetId.py @@ -0,0 +1,33 @@ +""" +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: MIT-0 +""" + +from __future__ import annotations + +from typing import Any + +import regex as re + +from cfnlint.jsonschema import Validator +from cfnlint.rules.formats.FormatKeyword import FormatKeyword + + +class SubnetId(FormatKeyword): + id = "E1154" + shortdesc = "Validate VPC subnet id format" + description = "Check that a VPC subnet id matches a pattern" + tags = [] + source_url = "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Subnet.Id" + + def __init__(self): + super().__init__(format="AWS::EC2::Subnet.Id") + + def format(self, validator: Validator, instance: Any) -> bool: + if not isinstance(instance, str): + return True + + if re.match(r"^subnet-(([0-9A-Fa-f]{8})|([0-9A-Fa-f]{17}))$", instance): + return True + + return False diff --git a/test/unit/rules/formats/test_subnet_id.py b/test/unit/rules/formats/test_subnet_id.py new file mode 100644 index 0000000000..e11a7496ff --- /dev/null +++ b/test/unit/rules/formats/test_subnet_id.py @@ -0,0 +1,40 @@ +""" +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: MIT-0 +""" + +import pytest + +from cfnlint.rules.formats.SubnetId import SubnetId + + +@pytest.fixture(scope="module") +def rule(): + rule = SubnetId() + yield rule + + +@pytest.mark.parametrize( + "name,instance,expected", + [ + ( + "Valid subnet id", + "subnet-abcd1234", + True, + ), + ( + "Valid subnet id long", + "subnet-abcdefa1234567890", + True, + ), + ( + "Valid but wrong type", + [], + True, + ), + ("Invalid subnet ID", "subnet-abc", False), + ], +) +def test_validate(name, instance, expected, rule, validator): + result = rule.format(validator, instance) + assert result == expected, f"Test {name!r} got {result!r}"