aboutsummaryrefslogtreecommitdiffstats
path: root/moon_cache/tests
diff options
context:
space:
mode:
Diffstat (limited to 'moon_cache/tests')
-rw-r--r--moon_cache/tests/unit_python/api/__init__.py11
-rw-r--r--moon_cache/tests/unit_python/api/test_attributes.py36
-rw-r--r--moon_cache/tests/unit_python/api/test_cache.py535
-rw-r--r--moon_cache/tests/unit_python/conftest.py151
-rw-r--r--moon_cache/tests/unit_python/mock_repo/__init__.py12
-rw-r--r--moon_cache/tests/unit_python/mock_repo/data.py306
-rw-r--r--moon_cache/tests/unit_python/mock_repo/urls.py174
-rw-r--r--moon_cache/tests/unit_python/requirements.txt7
8 files changed, 1232 insertions, 0 deletions
diff --git a/moon_cache/tests/unit_python/api/__init__.py b/moon_cache/tests/unit_python/api/__init__.py
new file mode 100644
index 00000000..582be686
--- /dev/null
+++ b/moon_cache/tests/unit_python/api/__init__.py
@@ -0,0 +1,11 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
diff --git a/moon_cache/tests/unit_python/api/test_attributes.py b/moon_cache/tests/unit_python/api/test_attributes.py
new file mode 100644
index 00000000..13bfc637
--- /dev/null
+++ b/moon_cache/tests/unit_python/api/test_attributes.py
@@ -0,0 +1,36 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+
+def test_get_attribute_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'mode'
+ value = "run"
+ cache_obj.set_attribute(name=name)
+ assert cache_obj.attributes
+ assert cache_obj.attributes.get(name)
+ assert cache_obj.attributes.get(name) == "build"
+ cache_obj.set_attribute(name=name, value=value)
+ assert cache_obj.attributes
+ assert cache_obj.attributes.get(name)
+ # Note: it is the same value because the cache systematically request the Manager
+ assert cache_obj.attributes.get(name) == "build"
+
+
+def test_get_attribute_unknown(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'test'
+ assert cache_obj.attributes
+ assert not cache_obj.attributes.get(name)
+
diff --git a/moon_cache/tests/unit_python/api/test_cache.py b/moon_cache/tests/unit_python/api/test_cache.py
new file mode 100644
index 00000000..52efb4e0
--- /dev/null
+++ b/moon_cache/tests/unit_python/api/test_cache.py
@@ -0,0 +1,535 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import pytest
+import mock_repo.data as data_mock
+import mock_repo.urls as register_urls
+import requests
+import requests_mock
+from moon_utilities import exceptions
+
+
+def test_authz_request(configuration):
+ from moon_cache import cache
+ c = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ assert isinstance(c.authz_requests, dict)
+
+
+# ================================
+# tests for get (subject) in cache
+# ================================
+
+def test_get_subject_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'subject_name'
+ subject_id = cache_obj.get_subject(data_mock.shared_ids["policy"]["policy_id_1"], name)
+ assert subject_id is not None
+
+
+def test_get_subject_no_policy(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ with pytest.raises(exceptions.PolicyUnknown) as exception_info:
+ cache_obj.get_subject(None, "")
+ assert str(exception_info.value) == '400: Policy Unknown'
+
+
+def test_get_subject_invalid_name(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'invalid name'
+ with pytest.raises(exceptions.SubjectUnknown) as exception_info:
+ cache_obj.get_subject(data_mock.shared_ids["policy"]["policy_id_1"], name)
+ assert str(exception_info.value) == '400: Subject Unknown'
+
+
+def test_get_subject_invalid_response(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'policy_id_invalid_response'
+ with pytest.raises(exceptions.SubjectUnknown) as exception_info:
+ cache_obj.get_subject(data_mock.shared_ids["policy"]["policy_id_invalid_response"], name)
+ assert str(exception_info.value) == '400: Subject Unknown'
+
+
+# ================================================
+# tests for get (object) in cache
+# ================================================
+
+def test_get_object_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'object_name'
+ object_id = cache_obj.get_object(data_mock.shared_ids["policy"]["policy_id_1"], name)
+ assert object_id is not None
+
+
+def test_get_object_no_policy(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ with pytest.raises(exceptions.PolicyUnknown) as exception_info:
+ cache_obj.get_object(None, "")
+ assert str(exception_info.value) == '400: Policy Unknown'
+
+
+def test_get_object_invalid_name(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'invalid name'
+ with pytest.raises(exceptions.ObjectUnknown) as exception_info:
+ cache_obj.get_object(data_mock.shared_ids["policy"]["policy_id_1"], name)
+ assert str(exception_info.value) == '400: Object Unknown'
+
+
+def test_get_object_invalid_response(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'policy_id_invalid_response'
+ with pytest.raises(exceptions.ObjectUnknown) as exception_info:
+ cache_obj.get_object(data_mock.shared_ids["policy"]["policy_id_invalid_response"], name)
+ assert str(exception_info.value) == '400: Object Unknown'
+
+
+# ================================================
+# tests for get (action) in cache
+# ================================================
+
+def test_get_action_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'action_name'
+ action_id = cache_obj.get_action(data_mock.shared_ids["policy"]["policy_id_1"], name)
+ assert action_id is not None
+
+
+def test_get_action_no_policy(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ with pytest.raises(exceptions.PolicyUnknown) as exception_info:
+ cache_obj.get_action(None, "")
+ assert str(exception_info.value) == '400: Policy Unknown'
+
+
+def test_get_action_invalid_name(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'invalid name'
+ with pytest.raises(exceptions.ActionUnknown) as exception_info:
+ cache_obj.get_action(data_mock.shared_ids["policy"]["policy_id_1"], name)
+ assert str(exception_info.value) == '400: Action Unknown'
+
+
+def test_get_action_invalid_response(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ name = 'policy_id_invalid_response'
+ with pytest.raises(exceptions.ActionUnknown) as exception_info:
+ cache_obj.get_action(data_mock.shared_ids["policy"]["policy_id_invalid_response"], name)
+ assert str(exception_info.value) == '400: Action Unknown'
+
+
+# ===========================================
+# tests for get (subject_assignment) in cache
+# ===========================================
+
+def test_get_subject_assignment_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ subject_assignments = cache_obj.get_subject_assignments(
+ data_mock.shared_ids["policy"]["policy_id_1"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert subject_assignments is not None
+
+
+def test_get_subject_assignment_no_policy(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ with pytest.raises(exceptions.PolicyUnknown) as exception_info:
+ cache_obj.get_subject_assignments(None,
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert str(exception_info.value) == '400: Policy Unknown'
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_subject_assignment_invalid_subject_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/subject_assignments/{}'
+ .format(
+ configuration["management"]["url"],
+ data_mock.shared_ids["subject"]["invalid_subject_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'subject_assignments':
+ data_mock.subject_assignment_mock_invalid_subject_id
+ }
+ )
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ subject_assignments = cache_obj.get_subject_assignments(
+ data_mock.shared_ids["subject"]["invalid_subject_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(subject_assignments) == 0
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_subject_assignment_invalid_category_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/subject_assignments/{}'
+ .format(
+ configuration["management"]["url"],
+ data_mock.shared_ids["subject"]["invalid_category_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'subject_assignments':
+ data_mock.subject_assignment_mock_invalid_category_id
+ }
+ )
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ subject_assignments = cache_obj.get_subject_assignments(
+ data_mock.shared_ids["subject"]["invalid_category_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(subject_assignments) == 0
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_subject_assignment_invalid_assignment_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/subject_assignments/{}'
+ .format(
+ configuration["management"]["url"],
+ data_mock.shared_ids["subject"]["invalid_assignment_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'subject_assignments':
+ data_mock.subject_assignment_mock_invalid_assignment_id
+ }
+ )
+
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ subject_assignments = cache_obj.get_subject_assignments(
+ data_mock.shared_ids["subject"]["invalid_assignment_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(subject_assignments) == 0
+
+
+def test_get_subject_assignment_empty_perimeter(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ subject_assignments = cache_obj.get_subject_assignments(
+ data_mock.shared_ids["policy"]["policy_id_2"],
+ None,
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(subject_assignments) == 0
+
+
+def test_get_subject_assignment_invalid_category_failure(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ subject_assignments = cache_obj.get_subject_assignments(
+ data_mock.shared_ids["policy"]["policy_id_1"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["invalid_category_id_1"])
+ assert len(subject_assignments) == 0
+
+
+# ==========================================
+# tests for get (object_assignment) in cache
+# ==========================================
+
+def test_get_object_assignment_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ object_assignments = cache_obj.get_object_assignments(
+ data_mock.shared_ids["policy"]["policy_id_1"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_2"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert object_assignments is not None
+
+
+def test_get_object_assignment_no_policy(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ with pytest.raises(exceptions.PolicyUnknown) as exception_info:
+ cache_obj.get_object_assignments(None,
+ data_mock.shared_ids["perimeter"]["perimeter_id_2"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert str(exception_info.value) == '400: Policy Unknown'
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_object_assignment_invalid_object_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/object_assignments/{}'
+ .format(configuration["management"]["url"],
+ data_mock.shared_ids["object"]["invalid_object_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'object_assignments':
+ data_mock.object_assignment_mock_invalid_object_id
+ }
+ )
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ object_assignments = cache_obj.get_object_assignments(
+ data_mock.shared_ids["object"]["invalid_object_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(object_assignments) == 0
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_object_assignment_invalid_category_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/object_assignments/{}'
+ .format(configuration["management"]["url"],
+ data_mock.shared_ids["object"]["invalid_category_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'object_assignments':
+ data_mock.object_assignment_mock_invalid_category_id
+ }
+ )
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ object_assignments = cache_obj.get_object_assignments(
+ data_mock.shared_ids["object"]["invalid_category_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(object_assignments) == 0
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_object_assignment_invalid_assignment_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/object_assignments/{}'
+ .format(configuration["management"]["url"],
+ data_mock.shared_ids["object"]["invalid_assignment_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'object_assignments':
+ data_mock.object_assignment_mock_invalid_assignment_id
+ }
+ )
+
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ object_assignments = cache_obj.get_object_assignments(
+ data_mock.shared_ids["object"]["invalid_assignment_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(object_assignments) == 0
+
+
+def test_get_object_assignment_none_perimeter(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ object_assignments = cache_obj.get_object_assignments(
+ data_mock.shared_ids["policy"]["policy_id_2"],
+ None,
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(object_assignments) == 0
+
+
+def test_get_object_assignment_invalid_category_failure(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ object_assignments = cache_obj.get_object_assignments(
+ data_mock.shared_ids["policy"]["policy_id_1"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_2"],
+ data_mock.shared_ids["category"]["invalid_category_id_1"])
+ assert len(object_assignments) == 0
+
+
+# ==========================================
+# tests for get (action_assignment) in cache
+# ==========================================
+
+def test_get_action_assignment_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ action_assignments = cache_obj.get_action_assignments(
+ data_mock.shared_ids["policy"]["policy_id_1"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_3"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert action_assignments is not None
+
+
+def test_get_action_assignment_no_policy(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ with pytest.raises(exceptions.PolicyUnknown) as exception_info:
+ cache_obj.get_action_assignments(None,
+ data_mock.shared_ids["perimeter"]["perimeter_id_2"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert str(exception_info.value) == '400: Policy Unknown'
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_action_assignment_invalid_object_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/action_assignments/{}'
+ .format(configuration["management"]["url"],
+ data_mock.shared_ids["action"]["invalid_action_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'action_assignments':
+ data_mock.action_assignment_mock_invalid_action_id
+ }
+ )
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ action_assignments = cache_obj.get_action_assignments(
+ data_mock.shared_ids["action"]["invalid_action_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(action_assignments) == 0
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_action_assignment_invalid_category_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/action_assignments/{}'
+ .format(configuration["management"]["url"],
+ data_mock.shared_ids["action"]["invalid_category_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'action_assignments':
+ data_mock.action_assignment_mock_invalid_category_id
+ }
+ )
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ action_assignments = cache_obj.get_action_assignments(
+ data_mock.shared_ids["action"]["invalid_category_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(action_assignments) == 0
+
+
+@requests_mock.Mocker(kw='mock')
+def test_get_action_assignment_invalid_assignment_id(configuration, **kwargs):
+ from moon_cache import cache
+ kwargs['mock'].get('{}/policies/{}/action_assignments/{}'
+ .format(configuration["management"]["url"],
+ data_mock.shared_ids["action"]["invalid_assignment_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"]),
+ json={
+ 'action_assignments':
+ data_mock.action_assignment_mock_invalid_assignment_id
+ }
+ )
+
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ action_assignments = cache_obj.get_action_assignments(
+ data_mock.shared_ids["action"]["invalid_assignment_id"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_1"],
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(action_assignments) == 0
+
+
+def test_get_action_assignment_none_perimeter(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ action_assignments = cache_obj.get_action_assignments(
+ data_mock.shared_ids["policy"]["policy_id_2"],
+ None,
+ data_mock.shared_ids["category"]["category_id_1"])
+ assert len(action_assignments) == 0
+
+
+def test_get_action_assignment_invalid_category_failure(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration["management"]["url"])
+ action_assignments = cache_obj.get_action_assignments(
+ data_mock.shared_ids["policy"]["policy_id_1"],
+ data_mock.shared_ids["perimeter"]["perimeter_id_3"],
+ data_mock.shared_ids["category"]["invalid_category_id_1"])
+ assert len(action_assignments) == 0
+
+
+# ==================================
+# tests for helper function in cache
+# ==================================
+
+def test_get_policy_from_meta_rules_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration.get("management")['url'])
+ policy_id = cache_obj.get_policy_from_meta_rules(
+ data_mock.shared_ids["meta_rule"]["meta_rule_id_1"])
+ assert policy_id is not None
+
+
+''' tests for containers function , security pipeline in cache which not used for now
+ need to mock pdp object, /pods correctly
+'''
+
+
+def test_get_policy_from_meta_rules_failure(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration.get("management")['url'])
+ meta_rule_id = 'meta_rule_id3'
+ policy_id = cache_obj.get_policy_from_meta_rules(meta_rule_id)
+ assert policy_id is None
+
+
+def test_get_pdp_from_vim_project_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration.get("management")['url'])
+ vim_project_id = 'vim_project_id1'
+ pdp_key = cache_obj.get_pdp_from_vim_project(vim_project_id)
+ assert pdp_key is not None
+
+
+def test_get_pdp_from_vim_project_failure(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration.get("management")['url'])
+ vim_project_id = 'vim_project_id2'
+ pdp_key = cache_obj.get_pdp_from_vim_project(vim_project_id)
+ assert pdp_key is None
+
+
+def test_get_vim_project_id_from_policy_id_success(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration.get("management")['url'])
+ vim_project_id = cache_obj.get_vim_project_id_from_policy_id(
+ data_mock.shared_ids["policy"]["policy_id_1"])
+ assert vim_project_id is not None
+
+
+def test_get_vim_project_id_from_policy_id_failure(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration.get("management")['url'])
+ policy_id = 'policy_id_3'
+ vim_project_id = cache_obj.get_vim_project_id_from_policy_id(policy_id)
+ assert vim_project_id is None
+
+
+def test_get_pipeline_url(configuration):
+ from moon_cache import cache
+ cache_obj = cache.Cache.getInstance(manager_url=configuration.get("management")['url'])
+ cache_obj.set_current_server(url="http://127.0.0.1:10000", api_key="")
+ cache_obj.add_pipeline("policy_id_1", {
+ "name": "test",
+ "description": "test",
+ "host": "127.0.0.1",
+ "port": 20000,
+ })
+ cache_obj.add_pipeline("policy_id_2", {
+ "name": "test",
+ "description": "test",
+ "host": "127.0.0.1",
+ "port": 20001,
+ })
+ url = cache_obj.get_pipeline_url(pipeline_id="policy_id_1")
+ assert url == "http://127.0.0.1:20000"
+ url = cache_obj.get_pipeline_url(pipeline_id="policy_id_2")
+ assert url == "http://127.0.0.1:20001"
diff --git a/moon_cache/tests/unit_python/conftest.py b/moon_cache/tests/unit_python/conftest.py
new file mode 100644
index 00000000..6b271d7a
--- /dev/null
+++ b/moon_cache/tests/unit_python/conftest.py
@@ -0,0 +1,151 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import pytest
+import requests_mock
+import yaml
+import mock_repo
+import mock_repo.urls as register_urls
+import mock_repo.data as data_mock
+
+__CONF = """
+database:
+ url: sqlite:////tmp/database_test.db
+ driver: moon_manager.plugins.sql
+ migration_dir: moon_manager.api.db.migrations
+
+management:
+ url: http://127.0.0.1:8000
+ user: admin
+ password: admin
+ token_file: /tmp/moon.pwd
+
+orchestration:
+ driver: moon_manager.plugins.pyorchestrator
+ connection: local
+ slaves:
+ port: 10000...10100
+ pipelines:
+ port: 20000...20100
+
+information:
+ driver: moon_manager.plugins.moon_openstack_plugin
+ openstack:
+ url: http://keystone:5000/v3
+ user: admin
+ password: p4ssw0rd
+ domain: default
+ project: admin
+ check_token: false
+ certificate: false
+
+plugins:
+ directory: /var/moon/plugins
+
+components:
+ manager:
+ port: 8080
+ bind: 0.0.0.0
+ hostname: manager
+
+logging:
+ version: 1
+
+ formatters:
+ brief:
+ format: "%(levelname)s %(name)s %(m, confessage)-30s"
+ custom:
+ format: "%(asctime)-15s %(levelname)s %(name)s %(m, confessage)s"
+
+ handlers:
+ console:
+ class : logging.StreamHandler
+ formatter: custom
+ level : INFO
+ stream : ext://sys.stdout
+ file:
+ class : logging.handlers.RotatingFileHandler
+ formatter: custom
+ level : DEBUG
+ filename: /tmp/moon.log
+ maxBytes: 1048576
+ backupCount: 3
+
+ loggers:
+ moon:
+ level: DEBUG
+ handlers: [console, file]
+ propagate: no
+
+ root:
+ level: ERROR
+ handlers: [console]
+"""
+
+
+@pytest.fixture
+def configuration():
+ return yaml.load(__CONF)
+
+
+def register_cache(m):
+ """ Modify the response from Requests module
+ """
+ conf = yaml.load(__CONF)
+ # register_urls.register_components(m, conf)
+ # register_urls.register_keystone(m, conf)
+
+ register_urls.register_pdp(m, conf)
+ register_urls.register_pipelines(m, conf)
+ register_urls.register_meta_rules(m, conf)
+ register_urls.register_policies(m, conf)
+ register_urls.register_slaves(m, conf)
+ register_urls.register_models(m, conf)
+
+ register_urls.register_policy_subject(m, conf, data_mock.shared_ids["policy"]["policy_id_1"])
+ register_urls.register_policy_subject_invalid_response(m, conf, data_mock.shared_ids["policy"]["policy_id_invalid_response"])
+
+ register_urls.register_policy_object(m, conf, data_mock.shared_ids["policy"]["policy_id_1"])
+ register_urls.register_policy_object_invalid_response(m, conf, data_mock.shared_ids["policy"]["policy_id_invalid_response"])
+
+ register_urls.register_policy_action(m, conf, data_mock.shared_ids["policy"]["policy_id_1"])
+ register_urls.register_policy_action_invalid_response(m, conf, data_mock.shared_ids["policy"]["policy_id_invalid_response"])
+
+ register_urls.register_policy_subject_assignment(m, conf, data_mock.shared_ids["policy"]["policy_id_1"], data_mock.shared_ids["perimeter"]["perimeter_id_1"])
+
+ register_urls.register_policy_subject_assignment_list(m, conf, data_mock.shared_ids["policy"]["policy_id_2"])
+
+ register_urls.register_policy_object_assignment(m, conf, data_mock.shared_ids["policy"]["policy_id_1"], data_mock.shared_ids["perimeter"]["perimeter_id_2"])
+
+ register_urls.register_policy_object_assignment_list(m, conf, data_mock.shared_ids["policy"]["policy_id_2"])
+
+ register_urls.register_policy_action_assignment(m, conf, data_mock.shared_ids["policy"]["policy_id_1"], data_mock.shared_ids["perimeter"]["perimeter_id_3"])
+
+ register_urls.register_policy_action_assignment_list(m, conf, data_mock.shared_ids["policy"]["policy_id_2"])
+
+ register_urls.register_attributes(m, conf)
+
+ # register_urls.register_policy_action_assignment(m, conf, "policy_id_2", "perimeter_id_2")
+ # register_urls.register_policy_action_assignment(m, conf, "policy_id_2", "perimeter_id_2")
+ # register_urls.register_policy_action_assignment(m, conf, "policy_id_2", "perimeter_id_2")
+
+ register_urls.register_rules(m, conf, "policy_id1")
+
+
+@pytest.fixture(autouse=True)
+def no_requests(monkeypatch):
+ """ Modify the response from Requests module
+ """
+ with requests_mock.Mocker(real_http=True) as m:
+ register_cache(m)
+ print("End registering URI")
+ yield m
diff --git a/moon_cache/tests/unit_python/mock_repo/__init__.py b/moon_cache/tests/unit_python/mock_repo/__init__.py
new file mode 100644
index 00000000..1856aa2c
--- /dev/null
+++ b/moon_cache/tests/unit_python/mock_repo/__init__.py
@@ -0,0 +1,12 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
diff --git a/moon_cache/tests/unit_python/mock_repo/data.py b/moon_cache/tests/unit_python/mock_repo/data.py
new file mode 100644
index 00000000..ff5e25a8
--- /dev/null
+++ b/moon_cache/tests/unit_python/mock_repo/data.py
@@ -0,0 +1,306 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+
+shared_ids = {
+ "policy": {
+ "policy_id_1": "policy_id_1",
+ "policy_id_2": "policy_id_2",
+ "policy_id_3": "policy_id_3",
+ "policy_id_invalid_response": "policy_id_invalid_response"
+ },
+ "category": {
+ "category_id_1": "category_id_1",
+ "invalid_category_id_1": " invalid_category_id_1"
+ },
+ "perimeter": {
+ "perimeter_id_1": "subject_id_1",
+ "perimeter_id_2": "object_id_1",
+ "perimeter_id_3": "action_id_1"
+ },
+ "meta_rule": {
+ "meta_rule_id_1": "meta_rule_id_1",
+ "meta_rule_id_2": "meta_rule_id_2"
+ },
+ "rule": {
+ "rule_id_1": "rule_id_2",
+ "rule_id_2": "rule_id_2"
+ },
+ "model": {
+ "model_id_1": "model_id_1"
+ },
+ "subject": {
+ "subject_id_1": "subject_id_1",
+ "invalid_subject_id": "invalid_subject_id",
+ "invalid_category_id": "invalid_category_id",
+ "invalid_assignment_id": "invalid_assignment_id"
+ },
+ "object": {
+ "object_id_1": "object_id_1",
+ "invalid_object_id": "invalid_object_id",
+ "invalid_category_id": "invalid_category_id",
+ "invalid_assignment_id": "invalid_assignment_id"
+ },
+ "action": {
+ "action_id_1": "action_id_1",
+ "invalid_action_id": "invalid_action_id",
+ "invalid_category_id": "invalid_category_id",
+ "invalid_assignment_id": "invalid_assignment_id"
+ }
+}
+
+pdp_mock = {
+ "pdp_id1": {
+ "name": "...",
+ "security_pipeline": ["policy_id_1", "policy_id_2"],
+ "vim_project_id": "vim_project_id1",
+ "description": "...",
+ }
+}
+
+meta_rules_mock = {
+ shared_ids["meta_rule"]["meta_rule_id_1"]: {
+ "name": "meta_rule1",
+ "algorithm": "name of the meta rule algorithm",
+ "subject_categories": ["subject_category_id1",
+ "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ },
+ shared_ids["meta_rule"]["meta_rule_id_2"]: {
+ "name": "name of the meta rules2",
+ "algorithm": "name of the meta rule algorithm",
+ "subject_categories": ["subject_category_id1",
+ "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ }
+}
+
+policies_mock = {
+ shared_ids["policy"]["policy_id_1"]: {
+ "name": "test_policy1",
+ "model_id": shared_ids["model"]["model_id_1"],
+ "genre": "authz",
+ "description": "test",
+ },
+ shared_ids["policy"]["policy_id_2"]: {
+ "name": "test_policy2",
+ "model_id": shared_ids["model"]["model_id_1"],
+ "genre": "authz",
+ "description": "test",
+ }
+}
+
+subject_mock = {
+ shared_ids["policy"]["policy_id_1"]: {
+ "subject_id": {
+ "name": "subject_name",
+ "vim_id": "vim_project_id1",
+ "description": "a description"
+ }
+ },
+ shared_ids["policy"]["policy_id_invalid_response"]: {
+ "subject_id": {
+ "name": "subject_name",
+ "vim_id": "vim_project_id1",
+ "description": "a description"
+ }
+ }
+
+}
+
+subject_assignment_mock = {
+ shared_ids["subject"]["subject_id_1"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "subject_id": "subject_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"],
+ }
+}
+
+subject_assignment_mock_invalid_subject_id = {
+ shared_ids["subject"]["invalid_subject_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "subject_id_invalid": "subject_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"],
+ }
+}
+
+subject_assignment_mock_invalid_category_id = {
+ shared_ids["subject"]["invalid_category_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "subject_id": "subject_id_1",
+ "category_id_invalid": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"],
+ }
+}
+
+subject_assignment_mock_invalid_assignment_id = {
+ shared_ids["subject"]["invalid_assignment_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "subject_id": "subject_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments_invalid": ["data_id_1, data_id_2"],
+ }
+}
+
+object_mock = {
+ shared_ids["policy"]["policy_id_1"]: {
+ "object_id": {
+ "name": "object_name",
+ "description": "a description"
+ }
+ }
+}
+
+object_assignment_mock = {
+ shared_ids["object"]["object_id_1"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "object_id": "object_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"]
+ }
+}
+
+object_assignment_mock_invalid_object_id = {
+ shared_ids["object"]["invalid_object_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "object_id": "object_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"]
+ }
+}
+
+object_assignment_mock_invalid_category_id = {
+ shared_ids["object"]["invalid_category_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "object_id": "object_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"]
+ }
+}
+
+object_assignment_mock_invalid_assignment_id = {
+ shared_ids["object"]["invalid_assignment_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "object_id": "object_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"]
+ }
+}
+
+action_mock = {
+ shared_ids["policy"]["policy_id_1"]: {
+ "action_id": {
+ "name": "action_name",
+ "description": "a description"
+ }
+ }
+}
+
+action_assignment_mock = {
+ shared_ids["action"]["action_id_1"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "action_id": "action_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"]
+ }
+}
+
+action_assignment_mock_invalid_action_id = {
+ shared_ids["action"]["invalid_action_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "action_id": "action_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"]
+ }
+}
+
+action_assignment_mock_invalid_category_id = {
+ shared_ids["action"]["invalid_category_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "action_id": "action_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"]
+ }
+}
+
+action_assignment_mock_invalid_assignment_id = {
+ shared_ids["action"]["invalid_assignment_id"]: {
+ "policy_id": shared_ids["policy"]["policy_id_1"],
+ "action_id": "action_id_1",
+ "category_id": shared_ids["category"]["category_id_1"],
+ "assignments": ["data_id_1, data_id_2"]
+ }
+}
+
+
+models_mock = {
+ shared_ids["model"]["model_id_1"]: {
+ "name": "test_model",
+ "description": "test",
+ "meta_rules": [shared_ids["meta_rule"]["meta_rule_id_1"]]
+ }
+}
+
+rules_mock = {
+ "rules": {
+ "meta_rule_id": shared_ids["meta_rule"]["meta_rule_id_1"],
+ shared_ids["rule"]["rule_id_1"]: {
+ "rule": ["subject_data_id1",
+ "object_data_id1",
+ "action_data_id1"],
+ "instructions": (
+ {"decision": "grant"},
+ # "grant" to immediately exit,
+ # "continue" to wait for the result of next policy
+ # "deny" to deny the request
+ )
+ },
+ shared_ids["rule"]["rule_id_2"]: {
+ "rule": ["subject_data_id2",
+ "object_data_id2",
+ "action_data_id2"],
+ "instructions": (
+ {
+ "update": {
+ "operation": "add",
+ # operations may be "add" or "delete"
+ "target": "rbac:role:admin"
+ # add the role admin to the current user
+ }
+ },
+ {"chain": {"name": "rbac"}}
+ # chain with the policy named rbac
+ )
+ }
+ }
+}
+
+pipelines_mock = {
+ "policy_id_1": {
+ "starttime": 1548688120.3931532,
+ "port": 20000,
+ "server_ip": "127.0.0.1",
+ "status": "up",
+ "log": "/tmp/moon_policy_id_1.log"
+ },
+ "policy_id_2": {
+ "starttime": 1548688120.3931532,
+ "port": 20001,
+ "server_ip": "127.0.0.1",
+ "status": "up",
+ "log": "/tmp/moon_policy_id_2.log"
+ }
+}
diff --git a/moon_cache/tests/unit_python/mock_repo/urls.py b/moon_cache/tests/unit_python/mock_repo/urls.py
new file mode 100644
index 00000000..4b6d5133
--- /dev/null
+++ b/moon_cache/tests/unit_python/mock_repo/urls.py
@@ -0,0 +1,174 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import mock_repo.data as data_mock
+
+
+def register_model_any(m, conf, module_name, mocked_data, key=None):
+ if key is None:
+ key = module_name
+ m.register_uri(
+ 'GET', '{}/{}'.format(conf['management']['url'],
+ module_name),
+
+ json={key: mocked_data}
+ )
+
+
+def register_policy_any(m, conf, policy_id, module_name, mocked_data, key=None):
+ if key is None:
+ key = module_name
+ m.register_uri(
+ 'GET', '{}/{}/{}/{}'.format(conf['management']['url'],
+ 'policies',
+ policy_id,
+ module_name),
+ json={key: mocked_data}
+ )
+
+
+def register_policy(m, conf, policy_id, mocked_data):
+ m.register_uri(
+ 'GET', '{}/{}/{}'.format(conf['management']['url'],
+ 'policies',
+ policy_id),
+ json={"policies": mocked_data}
+ )
+
+
+def register_pipelines(m, conf):
+ m.register_uri(
+ 'GET', 'http://127.0.0.1:20000/pipelines/policy_id_1',
+ json={'pipelines': data_mock.pipelines_mock}
+ )
+
+
+def register_slaves(m, conf):
+ m.register_uri(
+ 'GET', 'http://127.0.0.1:10000/pipelines',
+ json={'pipelines': data_mock.pipelines_mock}
+ )
+
+
+def register_pdp(m, conf):
+ register_model_any(m, conf, 'pdp', data_mock.pdp_mock, 'pdps')
+
+
+def register_meta_rules(m, conf):
+ register_model_any(m, conf, 'meta_rules', data_mock.meta_rules_mock)
+
+
+def register_policies(m, conf):
+ for _policy_id in data_mock.policies_mock:
+ register_policy(m, conf, _policy_id, data_mock.policies_mock[_policy_id])
+ register_model_any(m, conf, 'policies', data_mock.policies_mock)
+
+
+def register_models(m, conf):
+ register_model_any(m, conf, 'models', data_mock.models_mock)
+
+
+def register_policy_subject(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'subjects', data_mock.subject_mock[policy_id])
+
+
+def register_policy_subject_invalid_response(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'subjects', data_mock.subject_mock[policy_id],
+ 'subjects_invalid_key')
+
+
+def register_policy_object(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'objects', data_mock.object_mock[policy_id])
+
+
+def register_policy_object_invalid_response(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'objects', data_mock.subject_mock[policy_id],
+ 'objects_invalid_key')
+
+
+def register_policy_action(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'actions', data_mock.action_mock[policy_id])
+
+
+def register_policy_action_invalid_response(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'actions', data_mock.subject_mock[policy_id],
+ 'actions_invalid_key')
+
+
+def register_policy_subject_assignment_list(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'subject_assignments',
+ data_mock.subject_assignment_mock)
+
+
+def register_policy_object_assignment_list(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'object_assignments',
+ data_mock.object_assignment_mock)
+
+
+def register_policy_action_assignment_list(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'action_assignments',
+ data_mock.action_assignment_mock)
+
+
+def register_policy_subject_assignment(m, conf, policy_id, perimeter_id):
+ m.register_uri(
+ 'GET', '{}/{}/{}/subject_assignments/{}'.format(conf['management']['url'],
+ 'policies',
+ policy_id,
+ perimeter_id),
+ json={'subject_assignments': data_mock.subject_assignment_mock}
+ )
+
+
+def register_policy_object_assignment(m, conf, policy_id, perimeter_id):
+ m.register_uri(
+ 'GET', '{}/{}/{}/object_assignments/{}'.format(conf['management']['url'],
+ 'policies',
+ policy_id,
+ perimeter_id),
+ json={'object_assignments': data_mock.object_assignment_mock}
+ )
+
+
+def register_policy_action_assignment(m, conf, policy_id, perimeter_id):
+ m.register_uri(
+ 'GET', '{}/{}/{}/action_assignments/{}'.format(conf['management']['url'],
+ 'policies',
+ policy_id,
+ perimeter_id),
+ json={'action_assignments': data_mock.action_assignment_mock}
+ )
+
+
+def register_rules(m, conf, policy_id):
+ register_policy_any(m, conf, policy_id, 'rules', data_mock.rules_mock)
+
+
+def register_attributes(m, conf):
+ m.register_uri(
+ 'GET', 'http://127.0.0.1:8000/attributes/mode',
+ json={
+ 'attributes': {
+ 'id': 'mode', 'value': 'build', 'values': ['build', 'run'], 'default': 'run'
+ }
+ }
+ )
+ m.register_uri(
+ 'GET', 'http://127.0.0.1:8000/attributes',
+ json={
+ 'attributes': {
+ 'mode': {
+ 'id': 'mode', 'value': 'build', 'values': ['build', 'run'], 'default': 'run'}
+ }
+ }
+ )
+
diff --git a/moon_cache/tests/unit_python/requirements.txt b/moon_cache/tests/unit_python/requirements.txt
new file mode 100644
index 00000000..ca33f6d4
--- /dev/null
+++ b/moon_cache/tests/unit_python/requirements.txt
@@ -0,0 +1,7 @@
+pytest
+pytest-benchmark
+pbr
+pytest-cov
+cliff
+requests_mock
+moon_utilities \ No newline at end of file