PRODESC-5780: ACS Repo DAU APIs to also use non-attach allow list (#830)

* PRODSEC-5780: ACS Repo DAU APIs to also use non-attach allow list

- moved existing pre-configured allow list from remote-api to repository layer
- ("nodes.nonAttachContentTypes" xml -> "content.nonAttach.mimetypes" prop)
- now also used by DAU (as well as existing V1 REST API and CMIS to get/download content)
This commit is contained in:
montgolfiere
2021-12-07 17:21:31 +00:00
committed by GitHub
parent 2039018ce5
commit 89de2e4677
6 changed files with 55 additions and 24 deletions

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Remote API * Alfresco Remote API
* %% * %%
* Copyright (C) 2005 - 2016 Alfresco Software Limited * Copyright (C) 2005 - 2021 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -86,7 +86,8 @@ public abstract class CMISServletDispatcher implements CMISDispatcher
private boolean allowUnsecureCallbackJSONP; private boolean allowUnsecureCallbackJSONP;
private Set<String> nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf // pre-configured allow list of media/mime types, eg. specific types of images & also pdf
private Set<String> nonAttachContentTypes = Collections.emptySet();
public void setTenantAdminService(TenantAdminService tenantAdminService) public void setTenantAdminService(TenantAdminService tenantAdminService)
{ {
@@ -133,9 +134,12 @@ public abstract class CMISServletDispatcher implements CMISDispatcher
this.cmisVersion = CmisVersion.fromValue(cmisVersion); this.cmisVersion = CmisVersion.fromValue(cmisVersion);
} }
public void setNonAttachContentTypes(Set<String> nonAttachWhiteList) public void setNonAttachContentTypes(String nonAttachAllowListStr)
{ {
this.nonAttachContentTypes = nonAttachWhiteList; if ((nonAttachAllowListStr != null) && (! nonAttachAllowListStr.isEmpty()))
{
nonAttachContentTypes = Set.of(nonAttachAllowListStr.trim().split("\\s*,\\s*"));
}
} }
protected synchronized Descriptor getCurrentDescriptor() protected synchronized Descriptor getCurrentDescriptor()

View File

@@ -239,11 +239,15 @@ public class NodesImpl implements Nodes
private ConcurrentHashMap<String,NodeRef> ddCache = new ConcurrentHashMap<>(); private ConcurrentHashMap<String,NodeRef> ddCache = new ConcurrentHashMap<>();
private Set<String> nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf // pre-configured allow list of media/mime types, eg. specific types of images & also pdf
private Set<String> nonAttachContentTypes = Collections.emptySet();
public void setNonAttachContentTypes(Set<String> nonAttachWhiteList) public void setNonAttachContentTypes(String nonAttachAllowListStr)
{ {
this.nonAttachContentTypes = nonAttachWhiteList; if ((nonAttachAllowListStr != null) && (! nonAttachAllowListStr.isEmpty()))
{
nonAttachContentTypes = Set.of(nonAttachAllowListStr.trim().split("\\s*,\\s*"));
}
} }
public void init() public void init()

View File

@@ -509,19 +509,6 @@
</property> </property>
</bean> </bean>
<bean id="nodes.nonAttachContentTypes" class="org.springframework.beans.factory.config.SetFactoryBean">
<property name="sourceSet">
<set>
<value>application/pdf</value>
<value>image/jpeg</value>
<value>image/gif</value>
<value>image/png</value>
<value>image/tiff</value>
<value>image/bmp</value>
</set>
</property>
</bean>
<bean id="nodes.personLookupProperties" class="org.springframework.beans.factory.config.SetFactoryBean"> <bean id="nodes.personLookupProperties" class="org.springframework.beans.factory.config.SetFactoryBean">
<property name="sourceSet"> <property name="sourceSet">
<set> <set>
@@ -542,7 +529,7 @@
<property name="quickShareLinks" ref="QuickShareLinks"/> <property name="quickShareLinks" ref="QuickShareLinks"/>
<property name="behaviourFilter" ref="policyBehaviourFilter"/> <property name="behaviourFilter" ref="policyBehaviourFilter"/>
<property name="ignoreTypes" ref="nodes.ignoreTypes"/> <property name="ignoreTypes" ref="nodes.ignoreTypes"/>
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/> <property name="nonAttachContentTypes" value="${content.nonAttach.mimetypes}"/>
<property name="personLookupProperties" ref="nodes.personLookupProperties"/> <property name="personLookupProperties" ref="nodes.personLookupProperties"/>
<property name="poster" ref="activitiesPoster" /> <property name="poster" ref="activitiesPoster" />
<property name="smartStore" ref="smartStore"/> <property name="smartStore" ref="smartStore"/>
@@ -1142,7 +1129,7 @@
<property name="version" value="1.0"/> <property name="version" value="1.0"/>
<property name="cmisVersion" value="1.0"/> <property name="cmisVersion" value="1.0"/>
<property name="tenantAdminService" ref="tenantAdminService"/> <property name="tenantAdminService" ref="tenantAdminService"/>
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/> <property name="nonAttachContentTypes" value="${content.nonAttach.mimetypes}"/>
</bean> </bean>
<bean id="cmisAtomPubDispatcher1.1" class="org.alfresco.opencmis.PublicApiAtomPubCMISDispatcher" init-method="init"> <bean id="cmisAtomPubDispatcher1.1" class="org.alfresco.opencmis.PublicApiAtomPubCMISDispatcher" init-method="init">
@@ -1154,7 +1141,7 @@
<property name="version" value="1.1"/> <property name="version" value="1.1"/>
<property name="cmisVersion" value="1.1"/> <property name="cmisVersion" value="1.1"/>
<property name="tenantAdminService" ref="tenantAdminService"/> <property name="tenantAdminService" ref="tenantAdminService"/>
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/> <property name="nonAttachContentTypes" value="${content.nonAttach.mimetypes}"/>
</bean> </bean>
<bean id="cmisBrowserDispatcher1.1" class="org.alfresco.opencmis.PublicApiBrowserCMISDispatcher" init-method="init"> <bean id="cmisBrowserDispatcher1.1" class="org.alfresco.opencmis.PublicApiBrowserCMISDispatcher" init-method="init">
@@ -1166,7 +1153,7 @@
<property name="version" value="1.1"/> <property name="version" value="1.1"/>
<property name="cmisVersion" value="1.1"/> <property name="cmisVersion" value="1.1"/>
<property name="tenantAdminService" ref="tenantAdminService"/> <property name="tenantAdminService" ref="tenantAdminService"/>
<property name="nonAttachContentTypes" ref="nodes.nonAttachContentTypes"/> <property name="nonAttachContentTypes" value="${content.nonAttach.mimetypes}"/>
<property name="allowUnsecureCallbackJSONP" value="${allow.unsecure.callback.jsonp}"/> <property name="allowUnsecureCallbackJSONP" value="${allow.unsecure.callback.jsonp}"/>
</bean> </bean>

View File

@@ -28,6 +28,7 @@ package org.alfresco.repo.content;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -103,6 +104,9 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
private boolean ignoreEmptyContent; private boolean ignoreEmptyContent;
private SystemWideDirectUrlConfig systemWideDirectUrlConfig; private SystemWideDirectUrlConfig systemWideDirectUrlConfig;
/** pre-configured allow list of media/mime types, eg. specific types of images & also pdf */
private Set<String> nonAttachContentTypes = Collections.emptySet();
/** /**
* The policy component * The policy component
@@ -151,6 +155,14 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
this.systemWideDirectUrlConfig = systemWideDirectUrlConfig; this.systemWideDirectUrlConfig = systemWideDirectUrlConfig;
} }
public void setNonAttachContentTypes(String nonAttachAllowListStr)
{
if ((nonAttachAllowListStr != null) && (! nonAttachAllowListStr.isEmpty()))
{
nonAttachContentTypes = Set.of(nonAttachAllowListStr.trim().split("\\s*,\\s*"));
}
}
public void setPolicyComponent(PolicyComponent policyComponent) public void setPolicyComponent(PolicyComponent policyComponent)
{ {
this.policyComponent = policyComponent; this.policyComponent = policyComponent;
@@ -635,6 +647,7 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
String fileName = getFileName(nodeRef); String fileName = getFileName(nodeRef);
validFor = adjustValidFor(validFor); validFor = adjustValidFor(validFor);
attachment = adjustAttachment(nodeRef, contentMimetype, attachment);
DirectAccessUrl directAccessUrl = null; DirectAccessUrl directAccessUrl = null;
if (store.isContentDirectUrlEnabled()) if (store.isContentDirectUrlEnabled())
@@ -691,4 +704,21 @@ public class ContentServiceImpl implements ContentService, ApplicationContextAwa
} }
return validFor; return validFor;
} }
private boolean adjustAttachment(NodeRef nodeRef, String mimeType, boolean attachmentIn)
{
boolean attachment = true;
if (! attachmentIn)
{
if ((nonAttachContentTypes != null) && (nonAttachContentTypes.contains(mimeType)))
{
attachment = false;
}
else
{
logger.warn("Ignored attachment=false for " + nodeRef.getId() + " since " + mimeType + " is not in the whitelist for non-attach content types");
}
}
return attachment;
}
} }

View File

@@ -164,6 +164,9 @@
<property name="systemWideDirectUrlConfig" > <property name="systemWideDirectUrlConfig" >
<ref bean="systemWideDirectUrlConfig" /> <ref bean="systemWideDirectUrlConfig" />
</property> </property>
<property name="nonAttachContentTypes">
<value>${content.nonAttach.mimetypes}</value>
</property>
</bean> </bean>
<bean id="contentService" parent="baseContentService"> <bean id="contentService" parent="baseContentService">

View File

@@ -1317,3 +1317,6 @@ system.remove-alf_server-table-from-db.ignored=true
# When using JSONP, allows unsecure usage of "callback" functions. Disabled by default for security reasons # When using JSONP, allows unsecure usage of "callback" functions. Disabled by default for security reasons
allow.unsecure.callback.jsonp=false allow.unsecure.callback.jsonp=false
# pre-configured allow list of media/mime types to allow inline instead of attachment (via Content-Disposition response header)
content.nonAttach.mimetypes=application/pdf,image/jpeg,image/gif,image/png,image/tiff,image/bmp