Tower: upload cetmix_tower_server 16.0.2.2.9 (via marketplace)
This commit is contained in:
919
addons/cetmix_tower_server/tests/test_key.py
Normal file
919
addons/cetmix_tower_server/tests/test_key.py
Normal file
@@ -0,0 +1,919 @@
|
||||
from odoo.exceptions import AccessError, ValidationError
|
||||
|
||||
from .common import TestTowerCommon
|
||||
|
||||
|
||||
class TestTowerKey(TestTowerCommon):
|
||||
"""Test class for tower key."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
# Create another manager for testing
|
||||
cls.manager_2 = cls.Users.create(
|
||||
{
|
||||
"name": "Second Manager",
|
||||
"login": "manager2",
|
||||
"email": "manager2@test.com",
|
||||
"groups_id": [(4, cls.env.ref("cetmix_tower_server.group_manager").id)],
|
||||
}
|
||||
)
|
||||
|
||||
# Create test servers
|
||||
cls.server_1 = cls.Server.create(
|
||||
{
|
||||
"name": "Test Server 1",
|
||||
"ip_v4_address": "192.168.1.1",
|
||||
"ssh_port": 22,
|
||||
"ssh_username": "admin",
|
||||
"ssh_password": "password",
|
||||
"ssh_auth_mode": "p",
|
||||
}
|
||||
)
|
||||
cls.server_2 = cls.Server.create(
|
||||
{
|
||||
"name": "Test Server 2",
|
||||
"ip_v4_address": "192.168.1.2",
|
||||
"ssh_port": 22,
|
||||
"ssh_username": "admin",
|
||||
"ssh_password": "password",
|
||||
"ssh_auth_mode": "p",
|
||||
}
|
||||
)
|
||||
cls.test_key = cls.Key.create(
|
||||
{"name": "Test Key", "key_type": "s", "secret_value": "test value"}
|
||||
)
|
||||
|
||||
def test_key_creation(self):
|
||||
"""
|
||||
Test key creation.
|
||||
We override create method so need to check if reference is generated properly
|
||||
"""
|
||||
|
||||
# -- 1--
|
||||
# Check new key values
|
||||
key_one = self.Key.create(
|
||||
{"name": " test key meme ", "secret_value": "test value", "key_type": "s"}
|
||||
)
|
||||
self.assertEqual(
|
||||
key_one.reference, "test_key_meme", "Reference must be 'test_key_meme'"
|
||||
)
|
||||
self.assertEqual(
|
||||
key_one.name,
|
||||
"test key meme",
|
||||
"Trailing and leading whitespaces must be removed from name",
|
||||
)
|
||||
|
||||
def test_extract_key_strings(self):
|
||||
"""Check if key strings are extracted properly"""
|
||||
code = (
|
||||
"Hey #!cxtower.secret.MEME_KEY!# & Doge #!cxtower.secret.DOGE_KEY !# so "
|
||||
"like #!cxtower.secret.MEME_KEY!#!\n"
|
||||
"They make #!memes together."
|
||||
"And this is another string for the same #!cxtower.secret.MEME_KEY !#"
|
||||
)
|
||||
key_strings = self.Key._extract_key_strings(code)
|
||||
self.assertEqual(len(key_strings), 3, "Must be 3 key stings")
|
||||
self.assertIn(
|
||||
"#!cxtower.secret.MEME_KEY!#",
|
||||
key_strings,
|
||||
"Key string must be in key strings",
|
||||
)
|
||||
self.assertIn(
|
||||
"#!cxtower.secret.DOGE_KEY !#",
|
||||
key_strings,
|
||||
"Key string must be in key strings",
|
||||
)
|
||||
self.assertIn(
|
||||
"#!cxtower.secret.MEME_KEY !#",
|
||||
key_strings,
|
||||
"Key string must be in key strings",
|
||||
)
|
||||
|
||||
def test_parse_key_string(self):
|
||||
"""Check if key string is parsed correctly"""
|
||||
|
||||
# Test global key
|
||||
doge_key = self.Key.create(
|
||||
{
|
||||
"name": "doge key",
|
||||
"reference": "DOGE_KEY",
|
||||
"secret_value": "Doge dog",
|
||||
"key_type": "s",
|
||||
}
|
||||
)
|
||||
key_string = "#!cxtower.secret.DOGE_KEY!#"
|
||||
key_value = self.Key._parse_key_string(key_string)
|
||||
self.assertEqual(key_value, "Doge dog", "Key value doesn't match")
|
||||
|
||||
# Test the same key string but with some spaces before the key terminator
|
||||
key_string = "#!cxtower.secret.DOGE_KEY !#"
|
||||
key_value = self.Key._parse_key_string(key_string)
|
||||
self.assertEqual(key_value, "Doge dog", "Key value doesn't match")
|
||||
|
||||
# Test partner specific key
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": doge_key.id,
|
||||
"secret_value": "Doge partner",
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
# compose kwargs
|
||||
kwargs = {
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
key_value = self.Key._parse_key_string(key_string, **kwargs)
|
||||
self.assertEqual(key_value, "Doge partner", "Key value doesn't match")
|
||||
|
||||
# Test server specific key
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": doge_key.id,
|
||||
"secret_value": "Doge server",
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
)
|
||||
key_value = self.Key._parse_key_string(key_string, **kwargs)
|
||||
|
||||
# Test server and partner specific key
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": doge_key.id,
|
||||
"secret_value": "Doge server and partner",
|
||||
"server_id": self.server_test_1.id,
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
key_value = self.Key._parse_key_string(key_string, **kwargs)
|
||||
self.assertEqual(
|
||||
key_value, "Doge server and partner", "Key value doesn't match"
|
||||
)
|
||||
|
||||
# Test missing key
|
||||
key_string = "#!cxtower.secret.ANOTHER_KEY!#"
|
||||
key_value = self.Key._parse_key_string(key_string)
|
||||
self.assertIsNone(key_value, "Key value must be 'None'")
|
||||
|
||||
# Test missformatted key
|
||||
key_string = "#!cxtower.ANOTHER_KEY!#"
|
||||
key_value = self.Key._parse_key_string(key_string)
|
||||
self.assertIsNone(key_value, "Key value must be 'None'")
|
||||
|
||||
# Test another missformatted key
|
||||
key_string = "#!cxtower.notasecret.DOGE_KEY!#"
|
||||
key_value = self.Key._parse_key_string(key_string)
|
||||
self.assertIsNone(key_value, "Key value must be 'None'")
|
||||
|
||||
def test_resolve_key(self):
|
||||
"""Check generic key resolver"""
|
||||
self.Key.create(
|
||||
{
|
||||
"name": "doge key",
|
||||
"reference": "DOGE_KEY",
|
||||
"secret_value": "Doge dog",
|
||||
"key_type": "s",
|
||||
}
|
||||
)
|
||||
|
||||
# Existing key
|
||||
key_value = self.Key._resolve_key("secret", "DOGE_KEY")
|
||||
self.assertEqual(key_value, "Doge dog", "Key value doesn't match")
|
||||
|
||||
# Non existing key
|
||||
key_value = self.Key._resolve_key("server", "PEPE_KEY")
|
||||
self.assertIsNone(key_value, "Key value must be 'None'")
|
||||
|
||||
def test_resolve_key_type_secret(self):
|
||||
"""Check 'secret' type key resolver"""
|
||||
doge_key = self.Key.create(
|
||||
{
|
||||
"name": "doge key",
|
||||
"reference": "DOGE_KEY",
|
||||
"key_type": "s",
|
||||
}
|
||||
)
|
||||
|
||||
# 1. Test server and partner specific key
|
||||
server_partner_value = self.KeyValue.create(
|
||||
{
|
||||
"key_id": doge_key.id,
|
||||
"secret_value": "Doge server and partner",
|
||||
"server_id": self.server_test_1.id,
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
kwargs = {
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
key_value = self.Key._resolve_key_type_secret("DOGE_KEY", **kwargs)
|
||||
self.assertEqual(
|
||||
key_value, "Doge server and partner", "Key value doesn't match"
|
||||
)
|
||||
|
||||
# 2. Global key
|
||||
doge_key.write({"secret_value": "Doge dog"})
|
||||
key_value = self.Key._resolve_key_type_secret("DOGE_KEY")
|
||||
self.assertEqual(key_value, "Doge dog", "Key value doesn't match")
|
||||
|
||||
# 3. Non existing key
|
||||
key_value = self.Key._resolve_key_type_secret("PEPE_KEY")
|
||||
self.assertIsNone(key_value, "Key value must be 'None'")
|
||||
|
||||
# 4. Partner specific key
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": doge_key.id,
|
||||
"secret_value": "Doge partner",
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
kwargs = {
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
key_value = self.Key._resolve_key_type_secret("DOGE_KEY", **kwargs)
|
||||
self.assertEqual(key_value, "Doge partner", "Key value doesn't match")
|
||||
|
||||
# 5. Test server specific key
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": doge_key.id,
|
||||
"secret_value": "Doge server",
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
)
|
||||
kwargs = {
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
key_value = self.Key._resolve_key_type_secret("DOGE_KEY", **kwargs)
|
||||
self.assertEqual(key_value, "Doge server", "Key value doesn't match")
|
||||
|
||||
# 6. Test with non matching partner. Should return server specific value
|
||||
kwargs = {
|
||||
"partner_id": self.user.partner_id.id,
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
key_value = self.Key._resolve_key_type_secret("DOGE_KEY", **kwargs)
|
||||
self.assertEqual(key_value, "Doge server", "Key value doesn't match")
|
||||
|
||||
# 7. Change partner in the server-partner specific value.
|
||||
# Should return server specific value
|
||||
server_partner_value.write({"partner_id": self.manager.partner_id.id})
|
||||
kwargs = {
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
key_value = self.Key._resolve_key_type_secret("DOGE_KEY", **kwargs)
|
||||
self.assertEqual(key_value, "Doge server", "Key value doesn't match")
|
||||
|
||||
# 8. Test with the global key again
|
||||
key_value = self.Key._resolve_key_type_secret("DOGE_KEY")
|
||||
self.assertEqual(key_value, "Doge dog", "Key value doesn't match")
|
||||
|
||||
def test_parse_code(self):
|
||||
"""Test code parsing"""
|
||||
|
||||
def check_parsed_code(
|
||||
code, code_parsed_expected, expected_key_values=None, **kwargs
|
||||
):
|
||||
"""Helper function for code parse testing
|
||||
|
||||
Args:
|
||||
code (Text): code to parse
|
||||
code_parsed_expected (Text): expected parsed code
|
||||
expected_key_values (list, optional): key values that are expected
|
||||
to be returned. Defaults to None.
|
||||
"""
|
||||
code_parsed = self.Key._parse_code(code, **kwargs)
|
||||
self.assertEqual(
|
||||
code_parsed,
|
||||
code_parsed_expected,
|
||||
msg="Parsed code doesn't match expected one",
|
||||
)
|
||||
if expected_key_values:
|
||||
result = self.Key._parse_code_and_return_key_values(code, **kwargs)
|
||||
code_parsed = result["code"]
|
||||
key_values = result["key_values"]
|
||||
self.assertEqual(
|
||||
code_parsed,
|
||||
code_parsed_expected,
|
||||
msg="Parsed code doesn't match expected one",
|
||||
)
|
||||
self.assertEqual(
|
||||
len(key_values),
|
||||
len(expected_key_values),
|
||||
"Number of key values doesn't match number of expected ones",
|
||||
)
|
||||
for expected_value in expected_key_values:
|
||||
self.assertIn(
|
||||
expected_value,
|
||||
key_values,
|
||||
f"Value {expected_value} must be in the returned key values",
|
||||
)
|
||||
|
||||
# Create new key
|
||||
self.Key.create(
|
||||
{
|
||||
"name": "Meme key",
|
||||
"reference": "MEME_KEY",
|
||||
"secret_value": "Pepe Frog",
|
||||
"key_type": "s",
|
||||
}
|
||||
)
|
||||
|
||||
# Check key parser
|
||||
|
||||
# 1 - single line
|
||||
|
||||
code = "The key to understand this meme is #!cxtower.secret.MEME_KEY!#"
|
||||
code_parsed_expected = "The key to understand this meme is Pepe Frog"
|
||||
expected_key_values = ["Pepe Frog"]
|
||||
check_parsed_code(code, code_parsed_expected, expected_key_values)
|
||||
|
||||
# 2 - multi line
|
||||
code = "Welcome #!cxtower.secret.MEME_KEY!#\nNew hero of this city!"
|
||||
code_parsed_expected = "Welcome Pepe Frog\nNew hero of this city!"
|
||||
expected_key_values = ["Pepe Frog"]
|
||||
check_parsed_code(code, code_parsed_expected, expected_key_values)
|
||||
|
||||
# 3 - Key not found
|
||||
code = "Don't mess with #!cxtower.secret.DOGE_LIKE!# He will make you cry"
|
||||
code_parsed_expected = "Don't mess with None He will make you cry"
|
||||
expected_key_values = []
|
||||
check_parsed_code(code, code_parsed_expected, expected_key_values)
|
||||
|
||||
check_parsed_code(code, code_parsed_expected)
|
||||
|
||||
# 4 - Multi keys
|
||||
# Create new key
|
||||
doge_key = self.Key.create(
|
||||
{
|
||||
"name": "doge key",
|
||||
"reference": "DOGE_KEY",
|
||||
"secret_value": "Doge dog",
|
||||
"key_type": "s",
|
||||
}
|
||||
)
|
||||
code = (
|
||||
"Hey #!cxtower.secret.MEME_KEY!# & Doge #!cxtower.secret.DOGE_KEY !# so "
|
||||
"like #!cxtower.secret.MEME_KEY!#!\n"
|
||||
"They make #!memes together. Check #!cxtower.secret.MEME_KEY&#!"
|
||||
"cxtower.secret.DOGE_KEY"
|
||||
)
|
||||
code_parsed_expected = (
|
||||
"Hey Pepe Frog & Doge Doge dog so "
|
||||
"like Pepe Frog!\n"
|
||||
"They make #!memes together. Check #!cxtower.secret.MEME_KEY&#!"
|
||||
"cxtower.secret.DOGE_KEY"
|
||||
)
|
||||
expected_key_values = ["Pepe Frog", "Doge dog"]
|
||||
check_parsed_code(code, code_parsed_expected, expected_key_values)
|
||||
|
||||
# 5 - Partner specific key
|
||||
# Create new key for partner Bob
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": doge_key.id,
|
||||
"secret_value": "Doge wow",
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
# compose kwargs
|
||||
kwargs = {"partner_id": self.user_bob.partner_id.id}
|
||||
code_parsed_expected = (
|
||||
"Hey Pepe Frog & Doge Doge wow so "
|
||||
"like Pepe Frog!\n"
|
||||
"They make #!memes together. Check #!cxtower.secret.MEME_KEY&#!"
|
||||
"cxtower.secret.DOGE_KEY"
|
||||
)
|
||||
expected_key_values = ["Pepe Frog", "Doge wow"]
|
||||
check_parsed_code(code, code_parsed_expected, expected_key_values, **kwargs)
|
||||
|
||||
# 6 - Server specific key
|
||||
# Create new key for server Test 1
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": doge_key.id,
|
||||
"secret_value": "Doge much",
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
)
|
||||
# compose kwargs
|
||||
kwargs = {
|
||||
"partner_id": self.user_bob.partner_id.id, # not needed but may keep it
|
||||
"server_id": self.server_test_1.id,
|
||||
}
|
||||
code_parsed_expected = (
|
||||
"Hey Pepe Frog & Doge Doge much so "
|
||||
"like Pepe Frog!\n"
|
||||
"They make #!memes together. Check #!cxtower.secret.MEME_KEY&#!"
|
||||
"cxtower.secret.DOGE_KEY"
|
||||
)
|
||||
expected_key_values = ["Pepe Frog", "Doge much"]
|
||||
check_parsed_code(code, code_parsed_expected, expected_key_values, **kwargs)
|
||||
|
||||
def test_replace_with_spoiler(self):
|
||||
"""Check if secrets are replaced with spoiler correctly"""
|
||||
|
||||
code = (
|
||||
"Hey Pepe Frog & Doge Doge much so "
|
||||
"like Pepe Frog!\n"
|
||||
"They make #!memes together. Check #!cxtower.secret.MEME_KEY&#!"
|
||||
"cxtower.secret.DOGE_KEY"
|
||||
)
|
||||
placeholder = self.Key.SECRET_VALUE_PLACEHOLDER
|
||||
expected_code = (
|
||||
f"Hey {placeholder} & Doge {placeholder} so "
|
||||
f"like {placeholder}!\n"
|
||||
"They make #!memes together. Check #!cxtower.secret.MEME_KEY&#!"
|
||||
"cxtower.secret.DOGE_KEY"
|
||||
)
|
||||
key_values = ["Pepe Frog", "Doge much"]
|
||||
|
||||
result = self.Key._replace_with_spoiler(code, key_values)
|
||||
self.assertEqual(result, expected_code, "Result doesn't match expected code")
|
||||
|
||||
# --------------------------------------
|
||||
# Check with some random key values now
|
||||
# Original code should rename unchanged
|
||||
# --------------------------------------
|
||||
|
||||
key_values = ["Wow much", "No like"]
|
||||
result = self.Key._replace_with_spoiler(code, key_values)
|
||||
self.assertEqual(result, code, "Result doesn't match expected code")
|
||||
|
||||
def test_user_access(self):
|
||||
"""Test that regular users have no access to keys"""
|
||||
user_key = self.Key.with_user(self.user)
|
||||
|
||||
# Create test key
|
||||
key = self.Key.create(
|
||||
{"name": "Test Key", "secret_value": "test value", "key_type": "s"}
|
||||
)
|
||||
|
||||
# Test CRUD operations
|
||||
with self.assertRaises(AccessError):
|
||||
user_key.create(
|
||||
{"name": "New Key", "secret_value": "secret", "key_type": "s"}
|
||||
)
|
||||
with self.assertRaises(AccessError):
|
||||
user_key.browse(key.id).read(["name"])
|
||||
with self.assertRaises(AccessError):
|
||||
user_key.browse(key.id).write({"name": "Updated Name"})
|
||||
with self.assertRaises(AccessError):
|
||||
user_key.browse(key.id).unlink()
|
||||
|
||||
def test_manager_read_access(self):
|
||||
"""Test manager read access rules"""
|
||||
manager_key = self.Key.with_user(self.manager)
|
||||
|
||||
# Create test keys
|
||||
key_secret = self.Key.create(
|
||||
{"name": "Secret Key", "secret_value": "secret value", "key_type": "s"}
|
||||
)
|
||||
key_ssh = self.Key.create(
|
||||
{"name": "SSH Key", "secret_value": "ssh key", "key_type": "k"}
|
||||
)
|
||||
|
||||
# Test read access for secret key - should read (all managers can read secrets)
|
||||
self.assertTrue(manager_key.search([("id", "=", key_secret.id)]))
|
||||
|
||||
# Test read access for SSH key without server access - should not find
|
||||
self.assertFalse(manager_key.search([("id", "=", key_ssh.id)]))
|
||||
|
||||
# Add manager to server users and set SSH key - should find SSH key
|
||||
self.write_and_invalidate(
|
||||
self.server_1,
|
||||
**{"user_ids": [(4, self.manager.id)], "ssh_key_id": key_ssh.id},
|
||||
)
|
||||
self.assertTrue(manager_key.search([("id", "=", key_ssh.id)]))
|
||||
|
||||
# Remove key from server - should not find again
|
||||
self.server_1.write({"ssh_key_id": False})
|
||||
self.assertFalse(manager_key.search([("id", "=", key_ssh.id)]))
|
||||
|
||||
# Add as key user - should find both
|
||||
key_secret.write({"user_ids": [(4, self.manager.id)]})
|
||||
key_ssh.write({"user_ids": [(4, self.manager.id)]})
|
||||
self.assertTrue(manager_key.search([("id", "=", key_secret.id)]))
|
||||
self.assertTrue(manager_key.search([("id", "=", key_ssh.id)]))
|
||||
|
||||
def test_manager_write_access(self):
|
||||
"""Test manager write/create access rules"""
|
||||
manager_key = self.Key.with_user(self.manager)
|
||||
|
||||
# Create test keys as root and ensure manager is not in manager_ids
|
||||
key_secret = self.Key.create(
|
||||
{
|
||||
"name": "Secret Key",
|
||||
"secret_value": "secret value",
|
||||
"key_type": "s",
|
||||
"manager_ids": [(5, 0)], # Clear manager_ids
|
||||
}
|
||||
)
|
||||
key_ssh = self.Key.create(
|
||||
{
|
||||
"name": "SSH Key",
|
||||
"secret_value": "ssh key",
|
||||
"key_type": "k",
|
||||
"manager_ids": [(5, 0)], # Clear manager_ids
|
||||
}
|
||||
)
|
||||
|
||||
# Try write without being manager - should fail
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key.browse(key_secret.id).write({"name": "Updated Secret"})
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key.browse(key_ssh.id).write({"name": "Updated SSH"})
|
||||
|
||||
# Add as key manager - should write to secret
|
||||
key_secret.write({"manager_ids": [(4, self.manager.id)]})
|
||||
manager_key.browse(key_secret.id).write({"name": "Updated Secret"})
|
||||
self.assertEqual(key_secret.name, "Updated Secret")
|
||||
|
||||
# Add as server manager and set SSH key - should write to SSH key
|
||||
self.server_1.write(
|
||||
{"manager_ids": [(4, self.manager.id)], "ssh_key_id": key_ssh.id}
|
||||
)
|
||||
manager_key.browse(key_ssh.id).write({"name": "Updated SSH"})
|
||||
self.assertEqual(key_ssh.name, "Updated SSH")
|
||||
|
||||
def test_manager_create_access(self):
|
||||
"""Test manager create access rules"""
|
||||
manager_key = self.Key.with_user(self.manager)
|
||||
manager_2_key = self.Key.with_user(self.manager_2)
|
||||
|
||||
# Try create secret key when not a manager - should fail
|
||||
with self.assertRaises(AccessError):
|
||||
manager_2_key.create(
|
||||
{
|
||||
"name": "New Secret",
|
||||
"secret_value": "secret",
|
||||
"key_type": "s",
|
||||
"manager_ids": [(5, 0)], # Prevent automatic manager addition
|
||||
}
|
||||
)
|
||||
|
||||
# Try create SSH key when not a server manager - should fail
|
||||
with self.assertRaises(AccessError):
|
||||
manager_2_key.create(
|
||||
{
|
||||
"name": "New SSH",
|
||||
"secret_value": "ssh key",
|
||||
"key_type": "k",
|
||||
"manager_ids": [(5, 0)], # Prevent automatic manager addition
|
||||
}
|
||||
)
|
||||
|
||||
# Add as server manager - should create SSH key
|
||||
self.server_1.write({"manager_ids": [(4, self.manager.id)]})
|
||||
new_ssh_key = manager_key.create(
|
||||
{"name": "New SSH", "secret_value": "ssh key", "key_type": "k"}
|
||||
)
|
||||
# Link key to server
|
||||
self.server_1.write({"ssh_key_id": new_ssh_key.id})
|
||||
self.assertTrue(new_ssh_key.exists())
|
||||
|
||||
def test_manager_unlink_access(self):
|
||||
"""Test manager unlink access rules"""
|
||||
manager_key = self.Key.with_user(self.manager)
|
||||
|
||||
# Create keys as root
|
||||
key_secret = self.Key.create(
|
||||
{"name": "Secret Key", "secret_value": "secret value", "key_type": "s"}
|
||||
)
|
||||
key_ssh = self.Key.create(
|
||||
{"name": "SSH Key", "secret_value": "ssh key", "key_type": "k"}
|
||||
)
|
||||
# Link SSH key to server
|
||||
self.server_1.write({"ssh_key_id": key_ssh.id})
|
||||
|
||||
# Try delete without being manager and creator - should fail
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key.browse(key_secret.id).unlink()
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key.browse(key_ssh.id).unlink()
|
||||
|
||||
# Add as manager but not creator - should still fail
|
||||
key_secret.write({"manager_ids": [(4, self.manager.id)]})
|
||||
self.server_1.write({"manager_ids": [(4, self.manager.id)]})
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key.browse(key_secret.id).unlink()
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key.browse(key_ssh.id).unlink()
|
||||
|
||||
# Create own keys - should delete
|
||||
own_secret = manager_key.create(
|
||||
{
|
||||
"name": "Own Secret",
|
||||
"secret_value": "secret",
|
||||
"key_type": "s",
|
||||
"manager_ids": [(4, self.manager.id)],
|
||||
}
|
||||
)
|
||||
own_ssh = manager_key.create(
|
||||
{"name": "Own SSH", "secret_value": "ssh key", "key_type": "k"}
|
||||
)
|
||||
# Link own SSH key to server
|
||||
self.server_1.write({"ssh_key_id": own_ssh.id})
|
||||
|
||||
own_secret.unlink()
|
||||
own_ssh.unlink()
|
||||
self.assertFalse(own_secret.exists())
|
||||
self.assertFalse(own_ssh.exists())
|
||||
|
||||
def test_root_access(self):
|
||||
"""Test root access rules"""
|
||||
root_key = self.Key.with_user(self.root)
|
||||
|
||||
# Create
|
||||
key = root_key.create(
|
||||
{"name": "Root Key", "secret_value": "root secret", "key_type": "s"}
|
||||
)
|
||||
self.assertTrue(key.exists())
|
||||
|
||||
# Read
|
||||
self.assertEqual(root_key.browse(key.id).name, "Root Key")
|
||||
|
||||
# Write
|
||||
root_key.browse(key.id).write({"name": "Updated Root Key"})
|
||||
self.assertEqual(key.name, "Updated Root Key")
|
||||
|
||||
# Delete
|
||||
key.unlink()
|
||||
self.assertFalse(key.exists())
|
||||
|
||||
def test_key_value_user_access(self):
|
||||
"""Test that regular users have no access to key values"""
|
||||
user_key_value = self.KeyValue.with_user(self.user)
|
||||
|
||||
# Create test key and key value
|
||||
key = self.Key.create({"name": "Test Key", "key_type": "s"})
|
||||
key_value = self.KeyValue.create(
|
||||
{"key_id": key.id, "secret_value": "test value"}
|
||||
)
|
||||
|
||||
# Test CRUD operations
|
||||
with self.assertRaises(AccessError):
|
||||
user_key_value.create({"key_id": key.id, "secret_value": "new value"})
|
||||
with self.assertRaises(AccessError):
|
||||
user_key_value.browse(key_value.id).read(["secret_value"])
|
||||
with self.assertRaises(AccessError):
|
||||
user_key_value.browse(key_value.id).write({"secret_value": "updated value"})
|
||||
with self.assertRaises(AccessError):
|
||||
user_key_value.browse(key_value.id).unlink()
|
||||
|
||||
def test_key_value_manager_read_access(self):
|
||||
"""Test manager read access rules for key values"""
|
||||
manager_key_value = self.KeyValue.with_user(self.manager)
|
||||
|
||||
# Create test key and key values
|
||||
key = self.Key.create({"name": "Test Key", "key_type": "s"})
|
||||
global_value = self.KeyValue.create(
|
||||
{"key_id": key.id, "secret_value": "global value"}
|
||||
)
|
||||
server_value = self.KeyValue.create(
|
||||
{
|
||||
"key_id": key.id,
|
||||
"secret_value": "server value",
|
||||
"server_id": self.server_1.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Test read access - should not find without proper access
|
||||
self.assertTrue(manager_key_value.search([("id", "=", global_value.id)]))
|
||||
self.assertFalse(manager_key_value.search([("id", "=", server_value.id)]))
|
||||
|
||||
# Add as key user - should find global value and server value for that key
|
||||
key.write({"user_ids": [(4, self.manager.id)]})
|
||||
self.assertTrue(manager_key_value.search([("id", "=", global_value.id)]))
|
||||
self.assertTrue(manager_key_value.search([("id", "=", server_value.id)]))
|
||||
|
||||
# Remove from key users
|
||||
key.write({"user_ids": [(3, self.manager.id)]})
|
||||
self.assertTrue(manager_key_value.search([("id", "=", global_value.id)]))
|
||||
self.assertFalse(manager_key_value.search([("id", "=", server_value.id)]))
|
||||
|
||||
# Add as server user - should find server value
|
||||
self.server_1.write({"user_ids": [(4, self.manager.id)]})
|
||||
self.assertTrue(manager_key_value.search([("id", "=", global_value.id)]))
|
||||
self.assertTrue(manager_key_value.search([("id", "=", server_value.id)]))
|
||||
|
||||
def test_key_value_manager_write_access(self):
|
||||
"""Test manager write/create access rules for key values"""
|
||||
manager_key_value = self.KeyValue.with_user(self.manager)
|
||||
|
||||
# Create test key and key values
|
||||
key = self.Key.create({"name": "Test Key", "key_type": "s"})
|
||||
global_value = self.KeyValue.create(
|
||||
{"key_id": key.id, "secret_value": "global value"}
|
||||
)
|
||||
server_value = self.KeyValue.create(
|
||||
{
|
||||
"key_id": key.id,
|
||||
"secret_value": "server value",
|
||||
"server_id": self.server_1.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Try write without proper access - should fail
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key_value.browse(global_value.id).write(
|
||||
{"secret_value": "new value"}
|
||||
)
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key_value.browse(server_value.id).write(
|
||||
{"secret_value": "new value"}
|
||||
)
|
||||
|
||||
# Add as key manager - should write to global value
|
||||
key.write({"manager_ids": [(4, self.manager.id)]})
|
||||
manager_key_value.browse(global_value.id).write(
|
||||
{"secret_value": "updated global"}
|
||||
)
|
||||
self.assertEqual(
|
||||
global_value._get_secret_value("secret_value"), "updated global"
|
||||
)
|
||||
|
||||
# Add as server manager - should write to server value
|
||||
self.server_1.write({"manager_ids": [(4, self.manager.id)]})
|
||||
manager_key_value.browse(server_value.id).write(
|
||||
{"secret_value": "updated server"}
|
||||
)
|
||||
self.assertEqual(
|
||||
server_value._get_secret_value("secret_value"), "updated server"
|
||||
)
|
||||
|
||||
# Test create access
|
||||
for_bob = manager_key_value.create(
|
||||
{
|
||||
"key_id": key.id,
|
||||
"secret_value": "for bob",
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
self.assertTrue(for_bob.exists())
|
||||
|
||||
def test_key_value_manager_unlink_access(self):
|
||||
"""Test manager unlink access rules for key values"""
|
||||
manager_key_value = self.KeyValue.with_user(self.manager)
|
||||
|
||||
# Create test key and key values
|
||||
key = self.Key.create({"name": "Test Key", "key_type": "s"})
|
||||
|
||||
# Create values as root
|
||||
global_value = self.KeyValue.create(
|
||||
{"key_id": key.id, "secret_value": "global value"}
|
||||
)
|
||||
server_value = self.KeyValue.create(
|
||||
{
|
||||
"key_id": key.id,
|
||||
"secret_value": "server value",
|
||||
"server_id": self.server_1.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Try delete without proper access - should fail
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key_value.browse(global_value.id).unlink()
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key_value.browse(server_value.id).unlink()
|
||||
|
||||
# Add as manager but not creator - should still fail
|
||||
key.write({"manager_ids": [(4, self.manager.id)]})
|
||||
self.server_1.write({"manager_ids": [(4, self.manager.id)]})
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key_value.browse(global_value.id).unlink()
|
||||
with self.assertRaises(AccessError):
|
||||
manager_key_value.browse(server_value.id).unlink()
|
||||
|
||||
# Create own values - should delete
|
||||
own_partner_value = manager_key_value.create(
|
||||
{
|
||||
"key_id": key.id,
|
||||
"secret_value": "own partner",
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Unlink server value first to avoid constraint error
|
||||
server_value.unlink()
|
||||
|
||||
# Create server value
|
||||
own_server_value = manager_key_value.create(
|
||||
{
|
||||
"key_id": key.id,
|
||||
"secret_value": "own server",
|
||||
"server_id": self.server_1.id,
|
||||
}
|
||||
)
|
||||
|
||||
own_partner_value.unlink()
|
||||
own_server_value.unlink()
|
||||
self.assertFalse(own_partner_value.exists())
|
||||
self.assertFalse(own_server_value.exists())
|
||||
|
||||
def test_key_value_root_access(self):
|
||||
"""Test root access rules for key values"""
|
||||
root_key_value = self.KeyValue.with_user(self.root)
|
||||
|
||||
# Create test key
|
||||
key = self.Key.create({"name": "Test Key", "key_type": "s"})
|
||||
|
||||
# Create
|
||||
value = root_key_value.create({"key_id": key.id, "secret_value": "root value"})
|
||||
self.assertTrue(value.exists())
|
||||
|
||||
# Read
|
||||
self.assertEqual(
|
||||
root_key_value.browse(value.id)._get_secret_value("secret_value"),
|
||||
"root value",
|
||||
)
|
||||
|
||||
# Write
|
||||
root_key_value.browse(value.id).write({"secret_value": "updated value"})
|
||||
self.assertEqual(value._get_secret_value("secret_value"), "updated value")
|
||||
|
||||
# Delete
|
||||
value.unlink()
|
||||
self.assertFalse(value.exists())
|
||||
|
||||
def test_key_value_global_unique(self):
|
||||
"""Test global value uniqueness"""
|
||||
|
||||
# Try to create a value for the same key
|
||||
with self.assertRaises(ValidationError):
|
||||
another_global_value = self.KeyValue.create(
|
||||
{"key_id": self.test_key.id, "secret_value": "another test value"}
|
||||
)
|
||||
#
|
||||
another_global_value.unlink()
|
||||
|
||||
def test_key_value_server_unique(self):
|
||||
"""Test server value uniqueness"""
|
||||
# Create server tight value
|
||||
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": self.test_key.id,
|
||||
"secret_value": "server related",
|
||||
"server_id": self.server_1.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Try create another value for the same server
|
||||
with self.assertRaises(ValidationError):
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": self.test_key.id,
|
||||
"secret_value": "another server related",
|
||||
"server_id": self.server_1.id,
|
||||
}
|
||||
)
|
||||
|
||||
def test_key_value_partner_unique(self):
|
||||
"""Test partner value uniqueness"""
|
||||
# Create partner tight value
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": self.test_key.id,
|
||||
"secret_value": "partner related",
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Try create another value for the same partner
|
||||
with self.assertRaises(ValidationError):
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": self.test_key.id,
|
||||
"secret_value": "another partner related",
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
|
||||
def test_key_value_server_partner_unique(self):
|
||||
"""Test server and partner value uniqueness"""
|
||||
|
||||
# Create server and partner tight value
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": self.test_key.id,
|
||||
"secret_value": "server related",
|
||||
"server_id": self.server_1.id,
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
|
||||
# Try create another value for the same server and partner
|
||||
with self.assertRaises(ValidationError):
|
||||
self.KeyValue.create(
|
||||
{
|
||||
"key_id": self.test_key.id,
|
||||
"secret_value": "another server related",
|
||||
"server_id": self.server_1.id,
|
||||
"partner_id": self.user_bob.partner_id.id,
|
||||
}
|
||||
)
|
||||
Reference in New Issue
Block a user