diff --git a/repository/src/main/java/org/alfresco/repo/event2/NodeResourceHelper.java b/repository/src/main/java/org/alfresco/repo/event2/NodeResourceHelper.java index 76e7657ade..cb9f08576e 100644 --- a/repository/src/main/java/org/alfresco/repo/event2/NodeResourceHelper.java +++ b/repository/src/main/java/org/alfresco/repo/event2/NodeResourceHelper.java @@ -2,7 +2,7 @@ * #%L * Alfresco Repository * %% - * Copyright (C) 2005 - 2023 Alfresco Software Limited + * Copyright (C) 2005 - 2025 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of @@ -50,6 +50,7 @@ import org.alfresco.repo.event.v1.model.UserInfo; import org.alfresco.repo.event2.filter.EventFilterRegistry; import org.alfresco.repo.event2.filter.NodeAspectFilter; import org.alfresco.repo.event2.filter.NodePropertyFilter; +import org.alfresco.repo.event2.replacer.PropertyReplacer; import org.alfresco.repo.node.MLPropertyInterceptor; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; @@ -87,6 +88,7 @@ public class NodeResourceHelper implements InitializingBean protected EventFilterRegistry eventFilterRegistry; protected NamespaceService namespaceService; protected PermissionService permissionService; + protected PropertyReplacer propertyReplacer; private NodeAspectFilter nodeAspectFilter; private NodePropertyFilter nodePropertyFilter; @@ -100,6 +102,7 @@ public class NodeResourceHelper implements InitializingBean PropertyCheck.mandatory(this, "eventFilterRegistry", eventFilterRegistry); PropertyCheck.mandatory(this, "namespaceService", namespaceService); PropertyCheck.mandatory(this, "permissionService", permissionService); + PropertyCheck.mandatory(this, "propertyReplacer", propertyReplacer); this.nodeAspectFilter = eventFilterRegistry.getNodeAspectFilter(); this.nodePropertyFilter = eventFilterRegistry.getNodePropertyFilter(); @@ -137,6 +140,11 @@ public class NodeResourceHelper implements InitializingBean this.namespaceService = namespaceService; } + public void setPropertyReplacer(PropertyReplacer propertyReplacer) + { + this.propertyReplacer = propertyReplacer; + } + public NodeResource.Builder createNodeResourceBuilder(NodeRef nodeRef) { final QName type = nodeService.getType(nodeRef); @@ -215,8 +223,8 @@ public class NodeResourceHelper implements InitializingBean { v = ((MLText) v).getDefaultValue(); } - - filteredProps.put(getQNamePrefixString(k), v); + Serializable replacedValue = propertyReplacer.replace(k, v); + filteredProps.put(getQNamePrefixString(k), replacedValue); } }); @@ -232,7 +240,10 @@ public class NodeResourceHelper implements InitializingBean { final MLText mlTextValue = (MLText) v; final HashMap localizedValues = new HashMap<>(mlTextValue.size()); - mlTextValue.forEach((locale, text) -> localizedValues.put(locale.toString(), text)); + mlTextValue.forEach((locale, text) -> { + Serializable replacedValue = propertyReplacer.replace(k, v); + localizedValues.put(locale.toString(), replacedValue.toString()); + }); filteredProps.put(getQNamePrefixString(k), localizedValues); } }); diff --git a/repository/src/main/java/org/alfresco/repo/event2/replacer/PropertyReplacer.java b/repository/src/main/java/org/alfresco/repo/event2/replacer/PropertyReplacer.java new file mode 100644 index 0000000000..5e77edd432 --- /dev/null +++ b/repository/src/main/java/org/alfresco/repo/event2/replacer/PropertyReplacer.java @@ -0,0 +1,53 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2025 - 2025 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.event2.replacer; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.transfer.TransferModel; +import org.alfresco.service.namespace.QName; + +import java.io.Serializable; +import java.util.Set; + +public class PropertyReplacer +{ + private static final Set DEFAULT_SENSITIVE_PROPERTIES = Set.of( + ContentModel.PROP_PASSWORD, + ContentModel.PROP_SALT, + ContentModel.PROP_PASSWORD_HASH, + TransferModel.PROP_PASSWORD + ); + private static final String DEFAULT_REPLACEMENT_TEXT = "SENSITIVE_DATA_REMOVED"; + + public Serializable replace(QName propertyQName, Serializable value) + { + if (DEFAULT_SENSITIVE_PROPERTIES.contains(propertyQName)) + { + return DEFAULT_REPLACEMENT_TEXT; + } + return value; + } +} diff --git a/repository/src/main/resources/alfresco/events2-context.xml b/repository/src/main/resources/alfresco/events2-context.xml index aa5d78d1ba..fddf40a384 100644 --- a/repository/src/main/resources/alfresco/events2-context.xml +++ b/repository/src/main/resources/alfresco/events2-context.xml @@ -31,6 +31,8 @@ + + @@ -53,6 +55,7 @@ + diff --git a/repository/src/test/java/org/alfresco/repo/event2/replacer/PropertyReplacerUnitTest.java b/repository/src/test/java/org/alfresco/repo/event2/replacer/PropertyReplacerUnitTest.java new file mode 100644 index 0000000000..e004c382dd --- /dev/null +++ b/repository/src/test/java/org/alfresco/repo/event2/replacer/PropertyReplacerUnitTest.java @@ -0,0 +1,55 @@ +/* + * #%L + * Alfresco Repository + * %% + * Copyright (C) 2025 - 2025 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.repo.event2.replacer; + +import static org.junit.Assert.assertEquals; + +import java.util.UUID; + +import org.junit.Test; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.transfer.TransferModel; + +public class PropertyReplacerUnitTest +{ + private final PropertyReplacer propertyReplacer = new PropertyReplacer(); + + @Test + public void shouldReplacePropertyValueWhenItsOneOfTheDefaultSensitiveProperties() + { + assertEquals("SENSITIVE_DATA_REMOVED", propertyReplacer.replace(ContentModel.PROP_PASSWORD, "test_pass")); + assertEquals("SENSITIVE_DATA_REMOVED", propertyReplacer.replace(ContentModel.PROP_SALT, UUID.randomUUID().toString())); + assertEquals("SENSITIVE_DATA_REMOVED", propertyReplacer.replace(ContentModel.PROP_PASSWORD_HASH, "r4nD0M_h4sH")); + assertEquals("SENSITIVE_DATA_REMOVED", propertyReplacer.replace(TransferModel.PROP_PASSWORD, "pyramid")); + } + + @Test + public void shouldNotReplacePropertyValueWhenItsNotOneOfTheDefaultSensitiveProperties() + { + assertEquals("Bob", propertyReplacer.replace(ContentModel.PROP_USERNAME, "Bob")); + } +}