[MNT-24807] Implemented PropertyReplacer that replaces values of sensitive properties (e.g. passwords) during creation of NodeResource for event2

This commit is contained in:
cezary-witkowski
2025-01-15 12:14:36 +01:00
parent 35c01f78c3
commit 911ea4db23
4 changed files with 126 additions and 4 deletions

View File

@@ -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<String, String> 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);
}
});

View File

@@ -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 <http://www.gnu.org/licenses/>.
* #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<QName> 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;
}
}

View File

@@ -31,6 +31,8 @@
</bean>
<!-- End of Event2 Filters -->
<bean id="event2PropertyReplacer" class="org.alfresco.repo.event2.replacer.PropertyReplacer"/>
<bean id="baseEventGeneratorV2" abstract="true">
<property name="policyComponent" ref="policyComponent"/>
<property name="nodeService" ref="nodeService"/>
@@ -53,6 +55,7 @@
<property name="eventFilterRegistry" ref="event2FilterRegistry"/>
<property name="namespaceService" ref="namespaceService"/>
<property name="permissionService" ref="permissionService"/>
<property name="propertyReplacer" ref="event2PropertyReplacer"/>
</bean>
<bean id="baseEventSender" abstract="true">

View File

@@ -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 <http://www.gnu.org/licenses/>.
* #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"));
}
}