From 9010a2df4140e9c5119acea2bc14d2b5ecb921fc Mon Sep 17 00:00:00 2001 From: Liakh Artemii Date: Thu, 15 May 2025 15:53:37 +0300 Subject: [PATCH] restapi: Remove sensitive response fields for non-admin users Non-admin users can access detailed information such as MTU, CPU information, library information and other internal configuration data through network, host and storage domain API.This commit adds logic to remove these fields from responses for non-admin users to prevent unintentional data exposure. Fields that are required by the VM Portal are retained to ensure existing functionality is not broken. Signed-off-by: Liakh Artemii --- .../AbstractBackendNetworkResource.java | 13 ++++ .../AbstractBackendNetworksResource.java | 11 +++ .../BackendClusterNetworkResource.java | 7 +- .../BackendClusterNetworksResource.java | 4 +- .../BackendDataCenterNetworkResource.java | 7 +- .../BackendDataCenterNetworksResource.java | 1 + .../resource/BackendHostsResource.java | 20 +++++- .../BackendIscsiBondNetworkResource.java | 6 +- .../BackendIscsiBondNetworksResource.java | 4 +- .../resource/BackendNetworkResource.java | 6 +- .../resource/BackendNetworksResource.java | 2 + .../BackendStorageDomainResource.java | 21 +++++- .../BackendStorageDomainsResource.java | 17 ++++- .../restapi/resource/BaseBackendResource.java | 8 +++ .../engine/api/restapi/util/FieldCleaner.java | 52 ++++++++++++++ .../resource/AbstractBackendBaseTest.java | 1 + .../api/restapi/util/FieldCleanerTest.java | 72 +++++++++++++++++++ 17 files changed, 241 insertions(+), 11 deletions(-) create mode 100644 backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/util/FieldCleaner.java create mode 100644 backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/util/FieldCleanerTest.java diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendNetworkResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendNetworkResource.java index 6270f3a9d41..1c9e4a51930 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendNetworkResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendNetworkResource.java @@ -3,6 +3,7 @@ import javax.ws.rs.core.Response; import org.ovirt.engine.api.model.Network; +import org.ovirt.engine.api.restapi.util.FieldCleaner; import org.ovirt.engine.core.common.action.ActionParametersBase; import org.ovirt.engine.core.common.action.ActionType; @@ -29,6 +30,13 @@ public Network get() { return addLinks(map(entity)); } + protected void removeRestrictedInfo(Network network) { + // Filtered users are not allowed to view restricted information + if (!isAdmin()) { + nullifyRestrictedFields(network); + } + } + AbstractBackendNetworksResource getParent() { return parent; } @@ -44,4 +52,9 @@ public Response remove() { } return performAction(removeAction, getRemoveParameters(entity)); } + + public static void nullifyRestrictedFields(Network network) { + FieldCleaner.nullifyAllFieldsExcept(network, "id", "name", "dataCenter"); + FieldCleaner.nullifyAllFieldsExcept(network.getDataCenter(), "id"); + } } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendNetworksResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendNetworksResource.java index 3602f734260..45a95e88eb4 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendNetworksResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/AbstractBackendNetworksResource.java @@ -1,5 +1,7 @@ package org.ovirt.engine.api.restapi.resource; +import static org.ovirt.engine.api.restapi.resource.AbstractBackendNetworkResource.nullifyRestrictedFields; + import java.util.List; import org.ovirt.engine.api.model.BaseResource; @@ -31,6 +33,15 @@ public Networks list() { return mapCollection(getBackendCollection(queryType, getQueryParameters())); } + protected void removeRestrictedInfo(Networks networks) { + // Filtered users are not allowed to view restricted information + if (!isAdmin()) { + for (Network network : networks.getNetworks()) { + nullifyRestrictedFields(network); + } + } + } + protected Networks mapCollection(List entities) { Networks collection = new Networks(); for (org.ovirt.engine.core.common.businessentities.network.Network entity : entities) { diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterNetworkResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterNetworkResource.java index c5d28f7450b..df4a54a9ea1 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterNetworkResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterNetworkResource.java @@ -26,7 +26,12 @@ public Network get() { if (entity == null) { return notFound(); } - return addLinks(map(entity), Cluster.class); + + Network network = map(entity); + network = addLinks(network, Cluster.class); + removeRestrictedInfo(network); + + return network; } @Override diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterNetworksResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterNetworksResource.java index ea487b15572..b4b43a1c356 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterNetworksResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterNetworksResource.java @@ -31,8 +31,10 @@ public BackendClusterNetworksResource(String clusterId) { @Override public Networks list() { - return mapCollection(getBackendCollection(queryType, getQueryParameters()), + Networks networks = mapCollection(getBackendCollection(queryType, getQueryParameters()), org.ovirt.engine.api.model.Cluster.class); + removeRestrictedInfo(networks); + return networks; } @Override diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterNetworkResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterNetworkResource.java index 5f1fe56f842..3c533564034 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterNetworkResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterNetworkResource.java @@ -27,7 +27,12 @@ public Network get() { if (entity == null) { return notFound(); } - return addLinks(map(entity), LinkHelper.NO_PARENT); + + Network network = map(entity); + network = addLinks(network, LinkHelper.NO_PARENT); + removeRestrictedInfo(network); + + return network; } private org.ovirt.engine.core.common.businessentities.network.Network getNetwork() { diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterNetworksResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterNetworksResource.java index 329e924d62c..4c083a6dbad 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterNetworksResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterNetworksResource.java @@ -50,6 +50,7 @@ public Networks list() { for (Network network : networks.getNetworks()) { network.setDisplay(null); } + removeRestrictedInfo(networks); return networks; } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostsResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostsResource.java index 791ac5d5ce4..96a72d245e5 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostsResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendHostsResource.java @@ -12,6 +12,7 @@ import org.ovirt.engine.api.model.Hosts; import org.ovirt.engine.api.resource.HostResource; import org.ovirt.engine.api.resource.HostsResource; +import org.ovirt.engine.api.restapi.util.FieldCleaner; import org.ovirt.engine.api.restapi.util.ParametersHelper; import org.ovirt.engine.core.common.action.ActionType; import org.ovirt.engine.core.common.action.VdsOperationActionParameters; @@ -52,11 +53,16 @@ public BackendHostsResource() { @Override public Hosts list() { ApplicationMode appMode = getCurrent().getApplicationMode(); + + Hosts hosts; if (appMode == ApplicationMode.GlusterOnly) { - return listGlusterOnly(); + hosts = listGlusterOnly(); } else { - return listAll(); + hosts = listAll(); } + removeRestrictedInfo(hosts); + + return hosts; } private Hosts listGlusterOnly() { @@ -100,6 +106,16 @@ private Hosts listAll() { return mapCollection(getBackendCollection(SearchType.VDS)); } + private void removeRestrictedInfo(Hosts hosts) { + // Filtered users are not allowed to view restricted information + if (!isAdmin()) { + for (Host host : hosts.getHosts()) { + FieldCleaner.nullifyAllFieldsExcept(host, "id", "name", "address", "cluster"); + FieldCleaner.nullifyAllFieldsExcept(host.getCluster(), "id"); + } + } + } + @Override public HostResource getHostResource(String id) { return inject(new BackendHostResource(id, this)); diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendIscsiBondNetworkResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendIscsiBondNetworkResource.java index 0a1b6cb4b90..520ece0d3aa 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendIscsiBondNetworkResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendIscsiBondNetworkResource.java @@ -33,7 +33,11 @@ public Network get() { return notFound(); } - return addLinks(map(entity), LinkHelper.NO_PARENT); + Network network = map(entity); + network = addLinks(network, LinkHelper.NO_PARENT); + removeRestrictedInfo(network); + + return network; } private org.ovirt.engine.core.common.businessentities.network.Network getNetwork() { diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendIscsiBondNetworksResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendIscsiBondNetworksResource.java index 577f303c72e..b1d4c068162 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendIscsiBondNetworksResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendIscsiBondNetworksResource.java @@ -25,10 +25,12 @@ public BackendIscsiBondNetworksResource(String iscsiBondId) { @Override public Networks list() { - return mapCollection( + Networks networks = mapCollection( getBackendCollection(QueryType.GetNetworksByIscsiBondId, new IdQueryParameters(iscsiBondId)), LinkHelper.NO_PARENT ); + removeRestrictedInfo(networks); + return networks; } @Override diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendNetworkResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendNetworkResource.java index d080bd31a76..3ecdd40cf80 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendNetworkResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendNetworkResource.java @@ -27,9 +27,13 @@ public Network get() { if (entity == null) { return notFound(); } + Network network = map(entity); network.setDisplay(null); - return addLinks(network, LinkHelper.NO_PARENT); + network = addLinks(network, LinkHelper.NO_PARENT); + removeRestrictedInfo(network); + + return network; } @Override diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendNetworksResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendNetworksResource.java index 4f98afec02c..87c7f574f88 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendNetworksResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendNetworksResource.java @@ -60,6 +60,8 @@ public Networks list() { for (Network network : networks.getNetworks()) { network.setDisplay(null); } + removeRestrictedInfo(networks); + return networks; } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageDomainResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageDomainResource.java index 8ac00433f80..111a3bef103 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageDomainResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageDomainResource.java @@ -32,6 +32,7 @@ import org.ovirt.engine.api.resource.StorageDomainServerConnectionsResource; import org.ovirt.engine.api.resource.StorageDomainTemplatesResource; import org.ovirt.engine.api.resource.StorageDomainVmsResource; +import org.ovirt.engine.api.restapi.util.FieldCleaner; import org.ovirt.engine.api.restapi.util.ParametersHelper; import org.ovirt.engine.api.restapi.util.StorageDomainHelper; import org.ovirt.engine.core.common.VdcObjectType; @@ -77,7 +78,16 @@ BackendStorageDomainsResource getParent() { @Override public StorageDomain get() { StorageDomain storageDomain = performGet(QueryType.GetStorageDomainById, new IdQueryParameters(guid)); - return addLinks(storageDomain, getLinksToExclude(storageDomain)); + storageDomain = addLinks(storageDomain, getLinksToExclude(storageDomain)); + removeRestrictedInfo(storageDomain); + return storageDomain; + } + + private void removeRestrictedInfo(StorageDomain storageDomain) { + // Filtered users are not allowed to view restricted information + if (!isAdmin()) { + nullifyRestrictedFields(storageDomain); + } } @Override @@ -238,6 +248,15 @@ public static synchronized String[] getLinksToExclude(StorageDomain storageDomai : new String[] { "files", "images" }; } + public static void nullifyRestrictedFields(StorageDomain storageDomain) { + FieldCleaner.nullifyAllFieldsExcept( + storageDomain, "id", "name", "type", "permissions", + "storage", "available", "used", "status", "dataCenter", "links"); + FieldCleaner.nullifyAllFieldsExcept(storageDomain.getStorage(), "type"); + FieldCleaner.nullifyAllFieldsExcept(storageDomain.getDataCenter(), "id"); + FieldCleaner.removeAllLinksExcept(storageDomain, "permissions"); + } + /** * if user added new LUNs - extend the storage domain. */ diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageDomainsResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageDomainsResource.java index d8a316d3d04..28789f5f0a3 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageDomainsResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageDomainsResource.java @@ -1,6 +1,7 @@ package org.ovirt.engine.api.restapi.resource; import static org.ovirt.engine.api.restapi.resource.BackendStorageDomainResource.getLinksToExclude; +import static org.ovirt.engine.api.restapi.resource.BackendStorageDomainResource.nullifyRestrictedFields; import java.util.ArrayList; import java.util.Arrays; @@ -69,11 +70,23 @@ public BackendStorageDomainsResource() { @Override public StorageDomains list() { + StorageDomains storageDomains; if (isFiltered()) { - return mapCollection(getBackendCollection(QueryType.GetAllStorageDomains, + storageDomains = mapCollection(getBackendCollection(QueryType.GetAllStorageDomains, new QueryParametersBase(), SearchType.StorageDomain)); } else { - return mapCollection(getBackendCollection(SearchType.StorageDomain)); + storageDomains = mapCollection(getBackendCollection(SearchType.StorageDomain)); + } + removeRestrictedInfo(storageDomains); + return storageDomains; + } + + private void removeRestrictedInfo(StorageDomains storageDomains) { + // Filtered users are not allowed to view restricted information + if (!isAdmin()) { + for (StorageDomain storageDomain : storageDomains.getStorageDomains()) { + nullifyRestrictedFields(storageDomain); + } } } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BaseBackendResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BaseBackendResource.java index cd6489a9007..6dbe136efd3 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BaseBackendResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BaseBackendResource.java @@ -413,6 +413,14 @@ protected boolean isFiltered() { return result; } + /** + * @return true if current user has admin permission, otherwise false. + */ + protected boolean isAdmin() { + DbUser user = getCurrent().getUser(); + return user.isAdmin(); + } + /** * Follows links in the entity according to value of "follow" URL query parameter. * A valid value of'follow' is a comma separated list of strings, which represent diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/util/FieldCleaner.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/util/FieldCleaner.java new file mode 100644 index 00000000000..ebfe62d8131 --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/util/FieldCleaner.java @@ -0,0 +1,52 @@ +package org.ovirt.engine.api.restapi.util; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Set; + +import org.apache.commons.collections.CollectionUtils; +import org.ovirt.engine.api.model.BaseResource; +import org.ovirt.engine.api.model.Link; + +public class FieldCleaner { + + private FieldCleaner() { } + + public static void removeAllLinksExcept(BaseResource baseResource, String... allowedRel) { + List links = baseResource.getLinks(); + if (CollectionUtils.isEmpty(links)) { + return; + } + + Set allowedRelSet = Set.of(allowedRel); + links.removeIf(link -> !allowedRelSet.contains(link.getRel())); + } + + public static void nullifyAllFieldsExcept(Object obj, String... allowedFields) { + if (obj == null) { + return; + } + + Set allowedFieldSet = Set.of(allowedFields); + Class currentClass = obj.getClass(); + while (currentClass != null) { + for (Field field : currentClass.getDeclaredFields()) { + if (!allowedFieldSet.contains(field.getName())) { + nullifyField(obj, field); + } + } + currentClass = currentClass.getSuperclass(); + } + } + + private static void nullifyField(Object obj, Field field) { + try { + field.setAccessible(true); + if (!field.getType().isPrimitive()) { + field.set(obj, null); + } + } catch (Exception e) { + throw new RuntimeException("Failed to nullify field: " + field.getName(), e); + } + } +} diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendBaseTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendBaseTest.java index 5327e1b93b8..99a7c54257b 100644 --- a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendBaseTest.java +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/AbstractBackendBaseTest.java @@ -142,6 +142,7 @@ public void setUp() { currentUser.setLastName(USER); currentUser.setDomain(DOMAIN); currentUser.setNamespace(NAMESPACE); + currentUser.setAdmin(true); currentUser.setId(GUIDS[0]); Current current = new Current(); diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/util/FieldCleanerTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/util/FieldCleanerTest.java new file mode 100644 index 00000000000..fb4f30a6d1a --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/util/FieldCleanerTest.java @@ -0,0 +1,72 @@ +package org.ovirt.engine.api.restapi.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.ovirt.engine.api.model.Host; +import org.ovirt.engine.api.model.Link; +import org.ovirt.engine.api.model.Vm; +import org.ovirt.engine.core.compat.Guid; + +public class FieldCleanerTest { + + private static final String HOST_ID = Guid.newGuid().toString(); + private static final String VM_ID = Guid.newGuid().toString(); + + @Test + void testRemoveAllLinksExcept() { + Link link1 = new Link(); + link1.setRel("rel1"); + link1.setHref("href1"); + + Link link2 = new Link(); + link2.setRel("rel2"); + link2.setHref("href2"); + + Vm vm = createVm(); + vm.getLinks().addAll(List.of(link1, link2)); + + FieldCleaner.removeAllLinksExcept(vm, "rel2", "rel3"); + + List links = vm.getLinks(); + assertEquals(1, links.size()); + + Link link = links.get(0); + assertEquals("rel2", link.getRel()); + assertEquals("href2", link.getHref()); + } + + @Test + void testNullifyAllFieldsExcept() { + Vm vm = createVm(); + + FieldCleaner.nullifyAllFieldsExcept(vm, "id", "name", "host"); + FieldCleaner.nullifyAllFieldsExcept(vm.getHost(), "id"); + + assertEquals(VM_ID, vm.getId()); + assertNotNull(vm.getName()); + assertNull(vm.getDescription()); + + assertNotNull(vm.getHost()); + assertEquals(HOST_ID, vm.getHost().getId()); + assertNull(vm.getHost().getName()); + } + + private Vm createVm() { + Host host = new Host(); + host.setId(HOST_ID); + host.setName("host name"); + + Vm vm = new Vm(); + vm.setId(VM_ID); + vm.setName("vm name"); + vm.setDescription("vm description"); + vm.setHost(host); + + return vm; + } +}