Skip to content

Commit

Permalink
Add rule E3674 to validate instance PrivateIpAddress (#3657)
Browse files Browse the repository at this point in the history
  • Loading branch information
kddejong committed Sep 6, 2024
1 parent dfc305b commit ad55796
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"if": {
"required": [
"PrivateIpAddress"
]
},
"then": {
"properties": {
"NetworkInterfaces": {
"items": {
"properties": {
"PrivateIpAddresses": {
"items": {
"properties": {
"Primary": {
"enum": [
false
]
}
}
},
"type": "array"
}
}
},
"type": "array"
}
}
}
}
33 changes: 33 additions & 0 deletions src/cfnlint/rules/resources/ectwo/PrivateIpWithNetworkInterface.py
Original file line number Diff line number Diff line change
@@ -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 cfnlint.data.schemas.extensions.aws_ec2_instance
from cfnlint.jsonschema import ValidationError
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema, SchemaDetails


class PrivateIpWithNetworkInterface(CfnLintJsonSchema):
id = "E3674"
shortdesc = "Primary cannoy be True when PrivateIpAddress is specified"
description = "Only specify the private IP address for an instance in one spot"
tags = ["resources", "ec2"]

def __init__(self) -> None:
super().__init__(
keywords=[
"Resources/AWS::EC2::Instance/Properties",
],
schema_details=SchemaDetails(
module=cfnlint.data.schemas.extensions.aws_ec2_instance,
filename="privateipaddress.json",
),
)

def message(self, instance: Any, err: ValidationError) -> str:
return "'Primary' cannot be True when 'PrivateIpAddress' is specified"
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from collections import deque

import pytest

from cfnlint.jsonschema import ValidationError
from cfnlint.rules.resources.ectwo.PrivateIpWithNetworkInterface import (
PrivateIpWithNetworkInterface,
)


@pytest.fixture(scope="module")
def rule():
rule = PrivateIpWithNetworkInterface()
yield rule


@pytest.mark.parametrize(
"name,instance,path,expected",
[
(
"Valid with no Private Ip Address",
{
"NetworkInterfaces": [
{
"PrivateIpAddresses": [
{"PrivateIpAddress": "172.31.35.42", "Primary": True}
]
}
]
},
{
"path": ["Resources", "Instance", "Properties"],
},
[],
),
(
"Valid with Private Ip Address with Primary False",
{
"PrivateIpAddress": "172.31.35.42",
"NetworkInterfaces": [
{
"PrivateIpAddresses": [
{"PrivateIpAddress": "172.31.35.42", "Primary": False}
]
}
],
},
{
"path": ["Resources", "Instance", "Properties"],
},
[],
),
(
"Valid with Private Ip Address without Primary specified",
{
"PrivateIpAddress": "172.31.35.42",
"NetworkInterfaces": [
{"PrivateIpAddresses": [{"PrivateIpAddress": "172.31.35.42"}]}
],
},
{
"path": ["Resources", "Instance", "Properties"],
},
[],
),
(
"Invalid with a private ip address",
{
"PrivateIpAddress": "172.31.35.42",
"NetworkInterfaces": [
{
"PrivateIpAddresses": [
{"PrivateIpAddress": "172.31.35.42", "Primary": True}
]
}
],
},
{
"path": ["Resources", "Instance", "Properties"],
},
[
ValidationError(
"'Primary' cannot be True when 'PrivateIpAddress' is specified",
validator="enum",
rule=PrivateIpWithNetworkInterface(),
path=deque(
["NetworkInterfaces", 0, "PrivateIpAddresses", 0, "Primary"]
),
schema_path=deque(
[
"then",
"properties",
"NetworkInterfaces",
"items",
"properties",
"PrivateIpAddresses",
"items",
"properties",
"Primary",
"enum",
]
),
)
],
),
],
indirect=["path"],
)
def test_validate(name, instance, expected, rule, validator):
errs = list(rule.validate(validator, "", instance, {}))

assert (
errs == expected
), f"Expected test {name!r} to have {expected!r} but got {errs!r}"

0 comments on commit ad55796

Please sign in to comment.