mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 21:11:53 +00:00
feat(NHN): add NHN cloud provider with 6 checks (#6870)
Co-authored-by: MrCloudSec <hello@mistercloudsec.com>
This commit is contained in:
@@ -16,11 +16,11 @@ prowler_command = "prowler"
|
||||
|
||||
# capsys
|
||||
# https://docs.pytest.org/en/7.1.x/how-to/capture-stdout-stderr.html
|
||||
prowler_default_usage_error = "usage: prowler [-h] [--version] {aws,azure,gcp,kubernetes,microsoft365,dashboard} ..."
|
||||
prowler_default_usage_error = "usage: prowler [-h] [--version] {aws,azure,gcp,kubernetes,microsoft365,nhn,dashboard} ..."
|
||||
|
||||
|
||||
def mock_get_available_providers():
|
||||
return ["aws", "azure", "gcp", "kubernetes", "microsoft365"]
|
||||
return ["aws", "azure", "gcp", "kubernetes", "microsoft365", "nhn"]
|
||||
|
||||
|
||||
@pytest.mark.arg_parser
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
### Account, Check and/or Region can be * to apply for all the cases.
|
||||
### Resources and tags are lists that can have either Regex or Keywords.
|
||||
### Tags is an optional list that matches on tuples of 'key=value' and are "ANDed" together.
|
||||
### Use an alternation Regex to match one of multiple tags with "ORed" logic.
|
||||
### For each check you can except Accounts, Regions, Resources and/or Tags.
|
||||
########################### MUTELIST EXAMPLE ###########################
|
||||
Mutelist:
|
||||
Accounts:
|
||||
"subscription_1":
|
||||
Checks:
|
||||
"compute_instance_public_ip":
|
||||
Regions:
|
||||
- "*"
|
||||
Resources:
|
||||
- "resource_1"
|
||||
- "resource_2"
|
||||
@@ -0,0 +1,100 @@
|
||||
import yaml
|
||||
from mock import MagicMock
|
||||
|
||||
from prowler.providers.nhn.lib.mutelist.mutelist import NHNMutelist
|
||||
from tests.lib.outputs.fixtures.fixtures import generate_finding_output
|
||||
|
||||
MUTELIST_FIXTURE_PATH = "tests/providers/nhn/lib/mutelist/fixtures/nhn_mutelist.yaml"
|
||||
|
||||
|
||||
class TestNHNMutelist:
|
||||
def test_get_mutelist_file_from_local_file(self):
|
||||
mutelist = NHNMutelist(mutelist_path=MUTELIST_FIXTURE_PATH)
|
||||
|
||||
with open(MUTELIST_FIXTURE_PATH) as f:
|
||||
mutelist_fixture = yaml.safe_load(f)["Mutelist"]
|
||||
|
||||
assert mutelist.mutelist == mutelist_fixture
|
||||
assert mutelist.mutelist_file_path == MUTELIST_FIXTURE_PATH
|
||||
|
||||
def test_get_mutelist_file_from_local_file_non_existent(self):
|
||||
mutelist_path = "tests/lib/mutelist/fixtures/not_present"
|
||||
mutelist = NHNMutelist(mutelist_path=mutelist_path)
|
||||
|
||||
assert mutelist.mutelist == {}
|
||||
assert mutelist.mutelist_file_path == mutelist_path
|
||||
|
||||
def test_validate_mutelist_not_valid_key(self):
|
||||
mutelist_path = MUTELIST_FIXTURE_PATH
|
||||
with open(mutelist_path) as f:
|
||||
mutelist_fixture = yaml.safe_load(f)["Mutelist"]
|
||||
|
||||
mutelist_fixture["Accounts1"] = mutelist_fixture["Accounts"]
|
||||
del mutelist_fixture["Accounts"]
|
||||
|
||||
mutelist = NHNMutelist(mutelist_content=mutelist_fixture)
|
||||
|
||||
assert not mutelist.validate_mutelist()
|
||||
assert mutelist.mutelist == {}
|
||||
assert mutelist.mutelist_file_path is None
|
||||
|
||||
def test_is_finding_muted(self):
|
||||
# Mutelist
|
||||
mutelist_content = {
|
||||
"Accounts": {
|
||||
"resource_1": {
|
||||
"Checks": {
|
||||
"check_test": {
|
||||
"Regions": ["*"],
|
||||
"Resources": ["test_resource"],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutelist = NHNMutelist(mutelist_content=mutelist_content)
|
||||
|
||||
finding = MagicMock()
|
||||
finding.resource_id = "resource_1"
|
||||
finding.check_metadata = MagicMock()
|
||||
finding.check_metadata.CheckID = "check_test"
|
||||
finding.status = "FAIL"
|
||||
finding.resource_name = "test_resource"
|
||||
finding.location = "test_region"
|
||||
finding.resource_tags = []
|
||||
|
||||
assert mutelist.is_finding_muted(finding)
|
||||
|
||||
def test_mute_finding(self):
|
||||
# Mutelist
|
||||
mutelist_content = {
|
||||
"Accounts": {
|
||||
"resource_1": {
|
||||
"Checks": {
|
||||
"check_test": {
|
||||
"Regions": ["*"],
|
||||
"Resources": ["test_resource"],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutelist = NHNMutelist(mutelist_content=mutelist_content)
|
||||
|
||||
finding_1 = generate_finding_output(
|
||||
check_id="check_test",
|
||||
status="FAIL",
|
||||
account_uid="resource_1",
|
||||
region="test_region",
|
||||
resource_uid="test_resource",
|
||||
resource_tags=[],
|
||||
muted=False,
|
||||
)
|
||||
|
||||
muted_finding = mutelist.mute_finding(finding=finding_1)
|
||||
|
||||
assert muted_finding.status == "MUTED"
|
||||
assert muted_finding.muted
|
||||
assert muted_finding.raw["status"] == "FAIL"
|
||||
@@ -0,0 +1,29 @@
|
||||
from mock import MagicMock
|
||||
|
||||
from prowler.providers.nhn.nhn_provider import NhnProvider
|
||||
|
||||
|
||||
def set_mocked_nhn_provider(
|
||||
username="test_user",
|
||||
password="test_password",
|
||||
tenant_id="tenant123",
|
||||
audit_config=None,
|
||||
fixer_config=None,
|
||||
):
|
||||
"""
|
||||
Creates a mocked NHN Provider object for testing without real network calls.
|
||||
"""
|
||||
provider = MagicMock(spec=NhnProvider) # or just MagicMock()
|
||||
|
||||
provider.type = "nhn"
|
||||
provider._username = username
|
||||
provider._password = password
|
||||
provider._tenant_id = tenant_id
|
||||
provider._token = "fake_keystone_token"
|
||||
|
||||
provider.session = MagicMock()
|
||||
|
||||
provider.audit_config = audit_config
|
||||
provider.fixer_config = fixer_config
|
||||
|
||||
return provider
|
||||
@@ -0,0 +1,157 @@
|
||||
import os
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from prowler.providers.common.models import Connection
|
||||
from prowler.providers.nhn.nhn_provider import NhnProvider
|
||||
|
||||
|
||||
class TestNhnProvider:
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"NHN_USERNAME": "env_user",
|
||||
"NHN_PASSWORD": "env_pass",
|
||||
"NHN_TENANT_ID": "env_tenant",
|
||||
},
|
||||
)
|
||||
@patch("prowler.providers.nhn.nhn_provider.load_and_validate_config_file")
|
||||
@patch("requests.post")
|
||||
def test_nhn_provider_init_success(self, mock_post, mock_load_config):
|
||||
"""
|
||||
Test a successful initialization of NhnProvider
|
||||
with valid username/password/tenant_id and a Keystone token response = 200.
|
||||
"""
|
||||
# 1) Mock load_and_validate_config_file to avoid reading real config file
|
||||
mock_load_config.return_value = {}
|
||||
|
||||
# 2) Mock the requests.post to simulate a successful token response
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {
|
||||
"access": {"token": {"id": "fake_keystone_token"}}
|
||||
}
|
||||
mock_post.return_value = mock_response
|
||||
|
||||
# 3) Create provider
|
||||
provider = NhnProvider(
|
||||
username="test_user",
|
||||
password="test_pass",
|
||||
tenant_id="test_tenant",
|
||||
)
|
||||
|
||||
# 4) Assertions
|
||||
assert provider._token == "fake_keystone_token"
|
||||
assert provider.session is not None
|
||||
assert provider.session.headers["X-Auth-Token"] == "fake_keystone_token"
|
||||
|
||||
@patch.dict(os.environ, {}, clear=True)
|
||||
@patch(
|
||||
"prowler.providers.nhn.nhn_provider.load_and_validate_config_file",
|
||||
return_value={},
|
||||
)
|
||||
def test_nhn_provider_init_missing_args(self, mock_load_config):
|
||||
"""
|
||||
Test initialization when username/password/tenant_id is missing => ValueError
|
||||
"""
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
NhnProvider(username="", password="secret", tenant_id="tenant")
|
||||
assert "requires username, password and tenant_id" in str(exc_info.value)
|
||||
|
||||
@patch(
|
||||
"prowler.providers.nhn.nhn_provider.load_and_validate_config_file",
|
||||
return_value={},
|
||||
)
|
||||
@patch("requests.post")
|
||||
def test_nhn_provider_init_token_fail(self, mock_post, mock_load_config):
|
||||
"""
|
||||
Test the case where Keystone token request fails (non-200)
|
||||
=> provider._session remains None
|
||||
"""
|
||||
mock_post.return_value.status_code = 401
|
||||
mock_post.return_value.text = "Unauthorized"
|
||||
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
NhnProvider(
|
||||
username="test_user",
|
||||
password="test_pass",
|
||||
tenant_id="tenant123",
|
||||
)
|
||||
|
||||
assert "Failed to get NHN token" in str(exc_info.value)
|
||||
|
||||
@patch("prowler.providers.nhn.nhn_provider.requests")
|
||||
def test_test_connection_success(self, mock_requests):
|
||||
"""
|
||||
Test test_connection static method => success case
|
||||
"""
|
||||
# 1) Mock token success
|
||||
mock_post_response = MagicMock()
|
||||
mock_post_response.status_code = 200
|
||||
mock_post_response.json.return_value = {
|
||||
"access": {"token": {"id": "fake_keystone_token"}}
|
||||
}
|
||||
# 2) Mock /servers success
|
||||
mock_get_response = MagicMock()
|
||||
mock_get_response.status_code = 200
|
||||
mock_requests.post.return_value = mock_post_response
|
||||
mock_requests.get.return_value = mock_get_response
|
||||
|
||||
conn = NhnProvider.test_connection(
|
||||
username="test_user",
|
||||
password="test_pass",
|
||||
tenant_id="tenant123",
|
||||
raise_on_exception=True,
|
||||
)
|
||||
|
||||
assert isinstance(conn, Connection)
|
||||
assert conn.is_connected is True
|
||||
assert conn.error is None
|
||||
|
||||
@patch("prowler.providers.nhn.nhn_provider.requests")
|
||||
def test_test_connection_token_fail(self, mock_requests):
|
||||
"""
|
||||
Test test_connection => token request fails => returns Connection(error=...)
|
||||
"""
|
||||
mock_requests.post.return_value.status_code = 403
|
||||
mock_requests.post.return_value.text = "Forbidden"
|
||||
|
||||
conn = NhnProvider.test_connection(
|
||||
username="bad_user",
|
||||
password="bad_pass",
|
||||
tenant_id="tenant123",
|
||||
raise_on_exception=False, # so we don't raise, we get Connection object
|
||||
)
|
||||
assert conn.is_connected is False
|
||||
assert conn.error is not None
|
||||
assert "Failed to get token" in str(conn.error)
|
||||
|
||||
@patch("prowler.providers.nhn.nhn_provider.requests")
|
||||
def test_test_connection_servers_fail(self, mock_requests):
|
||||
"""
|
||||
Test test_connection => token OK, but /servers fails => returns Connection(error=...)
|
||||
"""
|
||||
# Keystone token success
|
||||
mock_post_response = MagicMock()
|
||||
mock_post_response.status_code = 200
|
||||
mock_post_response.json.return_value = {
|
||||
"access": {"token": {"id": "fake_keystone_token"}}
|
||||
}
|
||||
mock_requests.post.return_value = mock_post_response
|
||||
|
||||
# /servers fail
|
||||
mock_get_response = MagicMock()
|
||||
mock_get_response.status_code = 500
|
||||
mock_get_response.text = "Internal Server Error"
|
||||
mock_requests.get.return_value = mock_get_response
|
||||
|
||||
conn = NhnProvider.test_connection(
|
||||
username="test_user",
|
||||
password="test_pass",
|
||||
tenant_id="tenant123",
|
||||
raise_on_exception=False,
|
||||
)
|
||||
assert conn.is_connected is False
|
||||
assert conn.error is not None
|
||||
assert "/servers call failed" in str(conn.error)
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.nhn.services.compute.compute_service import Instance
|
||||
from tests.providers.nhn.nhn_fixtures import set_mocked_nhn_provider
|
||||
|
||||
|
||||
class Test_compute_instance_login_user:
|
||||
def test_no_instances(self):
|
||||
# 1) Make a MagicMock for compute_client
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.instances = []
|
||||
|
||||
# 2) Patch get_global_provider() to return a mocked NHN provider
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
# patch the 'compute_instance_login_user.compute_client' used in the check code
|
||||
"prowler.providers.nhn.services.compute.compute_instance_login_user.compute_instance_login_user.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
# 3) Import the check code AFTER patching
|
||||
from prowler.providers.nhn.services.compute.compute_instance_login_user.compute_instance_login_user import (
|
||||
compute_instance_login_user,
|
||||
)
|
||||
|
||||
# 4) Run the check
|
||||
check = compute_instance_login_user()
|
||||
result = check.execute()
|
||||
|
||||
# 5) Assertions
|
||||
assert len(result) == 0 # no instances => no findings
|
||||
|
||||
def test_has_instance_non_admin_login(self):
|
||||
# Make a MagicMock for compute_client
|
||||
compute_client = mock.MagicMock()
|
||||
|
||||
# Suppose we have 1 instance with login_user=False => PASS expected
|
||||
instance_id = str(uuid4())
|
||||
instance_name = "testVM"
|
||||
mock_instance = mock.MagicMock(spec=Instance)
|
||||
mock_instance.id = instance_id
|
||||
mock_instance.name = instance_name
|
||||
mock_instance.login_user = False # => means not admin login
|
||||
compute_client.instances = [mock_instance]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.compute.compute_instance_login_user.compute_instance_login_user.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.compute.compute_instance_login_user.compute_instance_login_user import (
|
||||
compute_instance_login_user,
|
||||
)
|
||||
|
||||
check = compute_instance_login_user()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert "has a appropriate login user" in result[0].status_extended
|
||||
assert result[0].resource_name == instance_name
|
||||
assert result[0].resource_id == instance_id
|
||||
|
||||
def test_has_instance_admin_login(self):
|
||||
# Another scenario: instance with login_user=True => FAIL expected
|
||||
compute_client = mock.MagicMock()
|
||||
|
||||
instance_id = str(uuid4())
|
||||
instance_name = "rootVM"
|
||||
mock_instance = mock.MagicMock(spec=Instance)
|
||||
mock_instance.id = instance_id
|
||||
mock_instance.name = instance_name
|
||||
mock_instance.login_user = True # => admin or root user
|
||||
compute_client.instances = [mock_instance]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.compute.compute_instance_login_user.compute_instance_login_user.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.compute.compute_instance_login_user.compute_instance_login_user import (
|
||||
compute_instance_login_user,
|
||||
)
|
||||
|
||||
check = compute_instance_login_user()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
"has an Administrative(admin/root) login user"
|
||||
in result[0].status_extended
|
||||
)
|
||||
assert result[0].resource_name == instance_name
|
||||
assert result[0].resource_id == instance_id
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.nhn.services.compute.compute_service import Instance
|
||||
from tests.providers.nhn.nhn_fixtures import set_mocked_nhn_provider
|
||||
|
||||
|
||||
class Test_compute_instance_public_ip:
|
||||
def test_no_instances(self):
|
||||
# 1) Make a MagicMock for compute_client
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.instances = []
|
||||
|
||||
# 2) Patch get_global_provider() to return a mocked NHN provider
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
# patch the 'compute_instance_public_ip.compute_client' used in the check code
|
||||
"prowler.providers.nhn.services.compute.compute_instance_public_ip.compute_instance_public_ip.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
# 3) Import the check code AFTER patching
|
||||
from prowler.providers.nhn.services.compute.compute_instance_public_ip.compute_instance_public_ip import (
|
||||
compute_instance_public_ip,
|
||||
)
|
||||
|
||||
# 4) Run the check
|
||||
check = compute_instance_public_ip()
|
||||
result = check.execute()
|
||||
|
||||
# 5) Assertions
|
||||
assert len(result) == 0 # no instances => no findings
|
||||
|
||||
def test_has_instance_non_public_ip(self):
|
||||
# Make a MagicMock for compute_client
|
||||
compute_client = mock.MagicMock()
|
||||
|
||||
# Suppose we have 1 instance with public_ip=False => PASS expected
|
||||
instance_id = str(uuid4())
|
||||
instance_name = "testVM"
|
||||
mock_instance = mock.MagicMock(spec=Instance)
|
||||
mock_instance.id = instance_id
|
||||
mock_instance.name = instance_name
|
||||
mock_instance.public_ip = False # => means does not have public IP
|
||||
compute_client.instances = [mock_instance]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.compute.compute_instance_public_ip.compute_instance_public_ip.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.compute.compute_instance_public_ip.compute_instance_public_ip import (
|
||||
compute_instance_public_ip,
|
||||
)
|
||||
|
||||
check = compute_instance_public_ip()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert "does not have a public IP" in result[0].status_extended
|
||||
assert result[0].resource_name == instance_name
|
||||
assert result[0].resource_id == instance_id
|
||||
|
||||
def test_has_instance_public_ip(self):
|
||||
# Another scenario: instance with public_ip=True => FAIL expected
|
||||
compute_client = mock.MagicMock()
|
||||
|
||||
instance_id = str(uuid4())
|
||||
instance_name = "rootVM"
|
||||
mock_instance = mock.MagicMock(spec=Instance)
|
||||
mock_instance.id = instance_id
|
||||
mock_instance.name = instance_name
|
||||
mock_instance.public_ip = True # => means has public IP
|
||||
compute_client.instances = [mock_instance]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.compute.compute_instance_public_ip.compute_instance_public_ip.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.compute.compute_instance_public_ip.compute_instance_public_ip import (
|
||||
compute_instance_public_ip,
|
||||
)
|
||||
|
||||
check = compute_instance_public_ip()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "has a public IP" in result[0].status_extended
|
||||
assert result[0].resource_name == instance_name
|
||||
assert result[0].resource_id == instance_id
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.nhn.services.compute.compute_service import Instance
|
||||
from tests.providers.nhn.nhn_fixtures import set_mocked_nhn_provider
|
||||
|
||||
|
||||
class Test_compute_instance_security_groups:
|
||||
def test_no_instances(self):
|
||||
# 1) Make a MagicMock for compute_client
|
||||
compute_client = mock.MagicMock()
|
||||
compute_client.instances = []
|
||||
|
||||
# 2) Patch get_global_provider() to return a mocked NHN provider
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
# patch the 'compute_instance_security_groups.compute_client' used in the check code
|
||||
"prowler.providers.nhn.services.compute.compute_instance_security_groups.compute_instance_security_groups.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
# 3) Import the check code AFTER patching
|
||||
from prowler.providers.nhn.services.compute.compute_instance_security_groups.compute_instance_security_groups import (
|
||||
compute_instance_security_groups,
|
||||
)
|
||||
|
||||
# 4) Run the check
|
||||
check = compute_instance_security_groups()
|
||||
result = check.execute()
|
||||
|
||||
# 5) Assertions
|
||||
assert len(result) == 0 # no instances => no findings
|
||||
|
||||
def test_has_instance_variety_security_groups(self):
|
||||
# Make a MagicMock for compute_client
|
||||
compute_client = mock.MagicMock()
|
||||
|
||||
# Suppose we have 1 instance with security_groups=False => PASS expected
|
||||
instance_id = str(uuid4())
|
||||
instance_name = "testVM"
|
||||
mock_instance = mock.MagicMock(spec=Instance)
|
||||
mock_instance.id = instance_id
|
||||
mock_instance.name = instance_name
|
||||
mock_instance.security_groups = False # => means has variety of security groups
|
||||
compute_client.instances = [mock_instance]
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.compute.compute_instance_security_groups.compute_instance_security_groups.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.compute.compute_instance_security_groups.compute_instance_security_groups import (
|
||||
compute_instance_security_groups,
|
||||
)
|
||||
|
||||
check = compute_instance_security_groups()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert "has a variety of security groups" in result[0].status_extended
|
||||
assert result[0].resource_name == instance_name
|
||||
assert result[0].resource_id == instance_id
|
||||
|
||||
def test_has_instance_security_groups(self):
|
||||
# Another scenario: instance with security_groups=True => FAIL expected
|
||||
compute_client = mock.MagicMock()
|
||||
|
||||
instance_id = str(uuid4())
|
||||
instance_name = "rootVM"
|
||||
mock_instance = mock.MagicMock(spec=Instance)
|
||||
mock_instance.id = instance_id
|
||||
mock_instance.name = instance_name
|
||||
mock_instance.security_groups = (
|
||||
True # => means has only the default security group
|
||||
)
|
||||
compute_client.instances = [mock_instance]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.compute.compute_instance_security_groups.compute_instance_security_groups.compute_client",
|
||||
new=compute_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.compute.compute_instance_security_groups.compute_instance_security_groups import (
|
||||
compute_instance_security_groups,
|
||||
)
|
||||
|
||||
check = compute_instance_security_groups()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "has only the default security group" in result[0].status_extended
|
||||
assert result[0].resource_name == instance_name
|
||||
assert result[0].resource_id == instance_id
|
||||
@@ -0,0 +1,100 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from prowler.providers.nhn.services.compute.compute_service import NHNComputeService
|
||||
from tests.providers.nhn.nhn_fixtures import set_mocked_nhn_provider
|
||||
|
||||
|
||||
class TestNHNComputeService:
|
||||
@patch("prowler.providers.nhn.services.compute.compute_service.logger")
|
||||
def test_compute_service_basic(self, mock_logger):
|
||||
"""
|
||||
Test that NHNComputeService properly calls _list_servers(),
|
||||
_get_server_detail() for each server, and populates self.instances.
|
||||
"""
|
||||
# create a mocked NHN Provider
|
||||
provider = set_mocked_nhn_provider(
|
||||
username="testUser",
|
||||
password="testPass",
|
||||
tenant_id="tenant123",
|
||||
)
|
||||
|
||||
# define mocked responses
|
||||
mocked_response_servers = MagicMock()
|
||||
mocked_response_servers.status_code = 200
|
||||
mocked_response_servers.json.return_value = {
|
||||
"servers": [
|
||||
{"id": "server1", "name": "myserver1"},
|
||||
{"id": "server2", "name": "myserver2"},
|
||||
]
|
||||
}
|
||||
|
||||
mocked_response_server1 = MagicMock()
|
||||
mocked_response_server1.status_code = 200
|
||||
mocked_response_server1.json.return_value = {
|
||||
"server": {
|
||||
"addresses": {
|
||||
"vpc1": [
|
||||
{"OS-EXT-IPS:type": "floating"},
|
||||
]
|
||||
},
|
||||
"security_groups": [{"name": "default"}],
|
||||
"metadata": {"login_username": "root"},
|
||||
}
|
||||
}
|
||||
|
||||
mocked_response_server2 = MagicMock()
|
||||
mocked_response_server2.status_code = 200
|
||||
mocked_response_server2.json.return_value = {
|
||||
"server": {
|
||||
"addresses": {
|
||||
"vpc1": [
|
||||
{"OS-EXT-IPS:type": "fixed"},
|
||||
]
|
||||
},
|
||||
"security_groups": [{"name": "default"}, {"name": "other-sg"}],
|
||||
"metadata": {"login_username": "regularuser"},
|
||||
}
|
||||
}
|
||||
|
||||
def get_side_effect(url, timeout=10):
|
||||
print(f"Called with timeout={timeout}")
|
||||
if (
|
||||
"/v2/tenant123/servers" in url
|
||||
and not url.endswith("server1")
|
||||
and not url.endswith("server2")
|
||||
):
|
||||
return mocked_response_servers
|
||||
elif url.endswith("server1"):
|
||||
return mocked_response_server1
|
||||
elif url.endswith("server2"):
|
||||
return mocked_response_server2
|
||||
else:
|
||||
mock_404 = MagicMock()
|
||||
mock_404.status_code = 404
|
||||
mock_404.text = "Not Found"
|
||||
return mock_404
|
||||
|
||||
provider.session.get.side_effect = get_side_effect
|
||||
|
||||
# create NHNComputeService, which internally calls _get_instances()
|
||||
compute_service = NHNComputeService(provider)
|
||||
|
||||
assert len(compute_service.instances) == 2
|
||||
|
||||
# first instance
|
||||
inst1 = compute_service.instances[0]
|
||||
assert inst1.id == "server1"
|
||||
assert inst1.name == "myserver1"
|
||||
assert inst1.public_ip is True
|
||||
assert inst1.security_groups is True
|
||||
assert inst1.login_user is True
|
||||
|
||||
# second instance
|
||||
inst2 = compute_service.instances[1]
|
||||
assert inst2.id == "server2"
|
||||
assert inst2.name == "myserver2"
|
||||
assert inst2.public_ip is False
|
||||
assert inst2.security_groups is False
|
||||
assert inst2.login_user is False
|
||||
|
||||
mock_logger.error.assert_not_called()
|
||||
@@ -0,0 +1,98 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from prowler.providers.nhn.services.network.network_service import NHNNetworkService
|
||||
from tests.providers.nhn.nhn_fixtures import set_mocked_nhn_provider
|
||||
|
||||
|
||||
class TestNHNNetworkService:
|
||||
@patch("prowler.providers.nhn.services.network.network_service.logger")
|
||||
def test_network_service_basic(self, mock_logger):
|
||||
"""
|
||||
Test that NHNNetworkService correctly calls _list_vpcs(),
|
||||
_get_vpc_detail() for each VPC, and populates self.networks and self.subnets.
|
||||
"""
|
||||
# create a mocked NHN Provider
|
||||
provider = set_mocked_nhn_provider(
|
||||
username="testUser",
|
||||
password="testPass",
|
||||
tenant_id="tenant123",
|
||||
)
|
||||
|
||||
# define mocked responses for VPCs and Subnets
|
||||
mocked_response_vpcs = MagicMock()
|
||||
mocked_response_vpcs.status_code = 200
|
||||
mocked_response_vpcs.json.return_value = {
|
||||
"vpcs": [
|
||||
{"id": "vpc1", "name": "myvpc1"},
|
||||
{"id": "vpc2", "name": "myvpc2"},
|
||||
]
|
||||
}
|
||||
|
||||
mocked_response_vpc1 = MagicMock()
|
||||
mocked_response_vpc1.status_code = 200
|
||||
mocked_response_vpc1.json.return_value = {
|
||||
"vpc": {
|
||||
"routingtables": [],
|
||||
"subnets": [
|
||||
{"name": "subnet1", "router:external": True, "enable_dhcp": False},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
mocked_response_vpc2 = MagicMock()
|
||||
mocked_response_vpc2.status_code = 200
|
||||
mocked_response_vpc2.json.return_value = {
|
||||
"vpc": {
|
||||
"routingtables": [{"id": "rt1"}],
|
||||
"subnets": [
|
||||
{"name": "subnet2", "router:external": False, "enable_dhcp": True},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
def get_side_effect(url, timeout=10):
|
||||
print(f"Called with timeout={timeout}")
|
||||
if (
|
||||
"/v2.0/vpcs" in url
|
||||
and not url.endswith("vpc1")
|
||||
and not url.endswith("vpc2")
|
||||
):
|
||||
return mocked_response_vpcs
|
||||
elif url.endswith("vpc1"):
|
||||
return mocked_response_vpc1
|
||||
elif url.endswith("vpc2"):
|
||||
return mocked_response_vpc2
|
||||
else:
|
||||
mock_404 = MagicMock()
|
||||
mock_404.status_code = 404
|
||||
mock_404.text = "Not Found"
|
||||
return mock_404
|
||||
|
||||
provider.session.get.side_effect = get_side_effect
|
||||
|
||||
# create NHNNetworkService, which internally calls _get_networks() and _get_subnets()
|
||||
network_service = NHNNetworkService(provider)
|
||||
|
||||
assert len(network_service.networks) == 2
|
||||
|
||||
# first network
|
||||
net1 = network_service.networks[0]
|
||||
assert net1.id == "vpc1"
|
||||
assert net1.name == "myvpc1"
|
||||
assert net1.empty_routingtables is True
|
||||
assert len(net1.subnets) == 1
|
||||
assert net1.subnets[0].name == "subnet1"
|
||||
assert net1.subnets[0].external_router is True
|
||||
assert net1.subnets[0].enable_dhcp is False
|
||||
|
||||
# second network
|
||||
net2 = network_service.networks[1]
|
||||
assert net2.id == "vpc2"
|
||||
assert net2.name == "myvpc2"
|
||||
assert net2.empty_routingtables is False # Assuming there's a routing table
|
||||
assert len(net2.subnets) == 1
|
||||
assert net2.subnets[0].name == "subnet2"
|
||||
assert net2.subnets[0].external_router is False
|
||||
assert net2.subnets[0].enable_dhcp is True
|
||||
|
||||
mock_logger.error.assert_not_called()
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.nhn.services.network.network_service import Network
|
||||
from tests.providers.nhn.nhn_fixtures import set_mocked_nhn_provider
|
||||
|
||||
|
||||
class Test_vpc_has_empty_routingtables:
|
||||
def test_no_networks(self):
|
||||
# 1) Make a MagicMock for network_client
|
||||
network_client = mock.MagicMock()
|
||||
network_client.networks = []
|
||||
|
||||
# 2) Patch get_global_provider() to return a mocked NHN provider
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
# patch the 'network_empty_routingtables.network_client' used in the check code
|
||||
"prowler.providers.nhn.services.network.network_vpc_has_empty_routingtables.network_vpc_has_empty_routingtables.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
# 3) Import the check code AFTER patching
|
||||
from prowler.providers.nhn.services.network.network_vpc_has_empty_routingtables.network_vpc_has_empty_routingtables import (
|
||||
network_vpc_has_empty_routingtables,
|
||||
)
|
||||
|
||||
# 4) Run the check
|
||||
check = network_vpc_has_empty_routingtables()
|
||||
result = check.execute()
|
||||
|
||||
# 5) Assertions
|
||||
assert len(result) == 0 # no networks => no findings
|
||||
|
||||
def test_vpc_has_empty_routingtables(self):
|
||||
# Make a MagicMock for network_client
|
||||
network_client = mock.MagicMock()
|
||||
|
||||
# Suppose we have 1 network with empty_routingtables=True => FAIL expected
|
||||
network_id = str(uuid4())
|
||||
network_name = "testNetwork"
|
||||
mock_network = mock.MagicMock(spec=Network)
|
||||
mock_network.id = network_id
|
||||
mock_network.name = network_name
|
||||
mock_network.empty_routingtables = True
|
||||
network_client.networks = [mock_network]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.network.network_vpc_has_empty_routingtables.network_vpc_has_empty_routingtables.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.network.network_vpc_has_empty_routingtables.network_vpc_has_empty_routingtables import (
|
||||
network_vpc_has_empty_routingtables,
|
||||
)
|
||||
|
||||
check = network_vpc_has_empty_routingtables()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "has empty routingtables" in result[0].status_extended
|
||||
assert result[0].resource_name == network_name
|
||||
assert result[0].resource_id == network_id
|
||||
|
||||
def test_vpc_does_not_have_empty_routingtables(self):
|
||||
# Another scenario: network with empty_routingtables=False => PASS expected
|
||||
network_client = mock.MagicMock()
|
||||
|
||||
network_id = str(uuid4())
|
||||
network_name = "testNetwork"
|
||||
mock_network = mock.MagicMock(spec=Network)
|
||||
mock_network.id = network_id
|
||||
mock_network.name = network_name
|
||||
mock_network.empty_routingtables = False
|
||||
network_client.networks = [mock_network]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.network.network_vpc_has_empty_routingtables.network_vpc_has_empty_routingtables.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.network.network_vpc_has_empty_routingtables.network_vpc_has_empty_routingtables import (
|
||||
network_vpc_has_empty_routingtables,
|
||||
)
|
||||
|
||||
check = network_vpc_has_empty_routingtables()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
assert result[0].status == "PASS"
|
||||
assert "dose not have empty routingtables" in result[0].status_extended
|
||||
assert result[0].resource_name == network_name
|
||||
assert result[0].resource_id == network_id
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.nhn.services.network.network_service import Network, Subnet
|
||||
from tests.providers.nhn.nhn_fixtures import set_mocked_nhn_provider
|
||||
|
||||
|
||||
class Test_network_vpc_subnet_enable_dhcp:
|
||||
def test_no_networks(self):
|
||||
# 1) Make a MagicMock for network_client
|
||||
network_client = mock.MagicMock()
|
||||
network_client.networks = []
|
||||
|
||||
# 2) Patch get_global_provider() to return a mocked NHN provider
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
# patch the 'network_vpc_subnet_enable_dhcp.network_client' used in the check code
|
||||
"prowler.providers.nhn.services.network.network_vpc_subnet_enable_dhcp.network_vpc_subnet_enable_dhcp.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
# 3) Import the check code AFTER patching
|
||||
from prowler.providers.nhn.services.network.network_vpc_subnet_enable_dhcp.network_vpc_subnet_enable_dhcp import (
|
||||
network_vpc_subnet_enable_dhcp,
|
||||
)
|
||||
|
||||
# 4) Run the check
|
||||
check = network_vpc_subnet_enable_dhcp()
|
||||
result = check.execute()
|
||||
|
||||
# 5) Assertions
|
||||
assert len(result) == 0 # no networks => no findings
|
||||
|
||||
def test_vpc_subnet_enable_dhcp(self):
|
||||
# Make a MagicMock for network_client
|
||||
network_client = mock.MagicMock()
|
||||
|
||||
# Suppose we have 1 network with enable_dhcp=True => FAIL expected
|
||||
network_id = str(uuid4())
|
||||
network_name = "testNetwork"
|
||||
mock_network = mock.MagicMock(spec=Network)
|
||||
mock_network.id = network_id
|
||||
mock_network.name = network_name
|
||||
mock_subnet = mock.MagicMock(spec=Subnet)
|
||||
mock_subnet.name = "subnet1"
|
||||
mock_subnet.enable_dhcp = True
|
||||
mock_network.subnets = [mock_subnet]
|
||||
network_client.networks = [mock_network]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.network.network_vpc_subnet_enable_dhcp.network_vpc_subnet_enable_dhcp.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.network.network_vpc_subnet_enable_dhcp.network_vpc_subnet_enable_dhcp import (
|
||||
network_vpc_subnet_enable_dhcp,
|
||||
)
|
||||
|
||||
check = network_vpc_subnet_enable_dhcp()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "has DHCP enabled" in result[0].status_extended
|
||||
assert result[0].resource_name == network_name
|
||||
assert result[0].resource_id == network_id
|
||||
|
||||
def test_vpc_subnet_unable_dhcp(self):
|
||||
# Another scenario: network with enable_dhcp=False => PASS expected
|
||||
network_client = mock.MagicMock()
|
||||
|
||||
network_id = str(uuid4())
|
||||
network_name = "testNetwork"
|
||||
mock_network = mock.MagicMock(spec=Network)
|
||||
mock_network.id = network_id
|
||||
mock_network.name = network_name
|
||||
mock_subnet = mock.MagicMock(spec=Subnet)
|
||||
mock_subnet.name = "subnet1"
|
||||
mock_subnet.enable_dhcp = False
|
||||
mock_network.subnets = [mock_subnet]
|
||||
network_client.networks = [mock_network]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.network.network_vpc_subnet_enable_dhcp.network_vpc_subnet_enable_dhcp.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.network.network_vpc_subnet_enable_dhcp.network_vpc_subnet_enable_dhcp import (
|
||||
network_vpc_subnet_enable_dhcp,
|
||||
)
|
||||
|
||||
check = network_vpc_subnet_enable_dhcp()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert "does not have DHCP enabled" in result[0].status_extended
|
||||
assert result[0].resource_name == network_name
|
||||
assert result[0].resource_id == network_id
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.nhn.services.network.network_service import Network, Subnet
|
||||
from tests.providers.nhn.nhn_fixtures import set_mocked_nhn_provider
|
||||
|
||||
|
||||
class Test_network_vpc_subnet_has_external_router:
|
||||
def test_no_networks(self):
|
||||
network_client = mock.MagicMock()
|
||||
network_client.networks = []
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.network.network_vpc_subnet_has_external_router.network_vpc_subnet_has_external_router.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.network.network_vpc_subnet_has_external_router.network_vpc_subnet_has_external_router import (
|
||||
network_vpc_subnet_has_external_router,
|
||||
)
|
||||
|
||||
check = network_vpc_subnet_has_external_router()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
def test_vpc_subnet_has_external_router(self):
|
||||
network_client = mock.MagicMock()
|
||||
|
||||
network_id = str(uuid4())
|
||||
network_name = "testNetwork"
|
||||
mock_network = mock.MagicMock(spec=Network)
|
||||
mock_network.id = network_id
|
||||
mock_network.name = network_name
|
||||
mock_subnet = mock.MagicMock(spec=Subnet)
|
||||
mock_subnet.name = "subnet1"
|
||||
mock_subnet.external_router = True
|
||||
mock_network.subnets = [mock_subnet]
|
||||
network_client.networks = [mock_network]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.network.network_vpc_subnet_has_external_router.network_vpc_subnet_has_external_router.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.network.network_vpc_subnet_has_external_router.network_vpc_subnet_has_external_router import (
|
||||
network_vpc_subnet_has_external_router,
|
||||
)
|
||||
|
||||
check = network_vpc_subnet_has_external_router()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "has external router" in result[0].status_extended
|
||||
assert result[0].resource_id == network_id
|
||||
assert result[0].resource_name == network_name
|
||||
|
||||
def test_vpc_subnet_no_external_router(self):
|
||||
network_client = mock.MagicMock()
|
||||
|
||||
network_id = str(uuid4())
|
||||
network_name = "testNetwork"
|
||||
mock_network = mock.MagicMock(spec=Network)
|
||||
mock_network.id = network_id
|
||||
mock_network.name = network_name
|
||||
mock_subnet = mock.MagicMock(spec=Subnet)
|
||||
mock_subnet.name = "subnet1"
|
||||
mock_subnet.external_router = False
|
||||
mock_network.subnets = [mock_subnet]
|
||||
network_client.networks = [mock_network]
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_nhn_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.nhn.services.network.network_vpc_subnet_has_external_router.network_vpc_subnet_has_external_router.network_client",
|
||||
new=network_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.nhn.services.network.network_vpc_subnet_has_external_router.network_vpc_subnet_has_external_router import (
|
||||
network_vpc_subnet_has_external_router,
|
||||
)
|
||||
|
||||
check = network_vpc_subnet_has_external_router()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert "no external router" in result[0].status_extended
|
||||
assert result[0].resource_id == network_id
|
||||
assert result[0].resource_name == network_name
|
||||
Reference in New Issue
Block a user