From a0f2d37153567c7573528417fcb963f187ed4cce Mon Sep 17 00:00:00 2001 From: Torsten Simon Date: Wed, 28 Aug 2024 15:15:39 +0200 Subject: [PATCH 1/3] fix:add options for headers X-Content-Type-Options and Referrer-Policy --- .../repository/server/SecurityHeadersFilter.java | 13 ++++++++++--- .../src/main/resources/edu-sharing.reference.conf | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/SecurityHeadersFilter.java b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/SecurityHeadersFilter.java index fff358768..40dd652c7 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/SecurityHeadersFilter.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/SecurityHeadersFilter.java @@ -12,6 +12,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; +import java.util.List; import java.util.Map; public class SecurityHeadersFilter implements Filter { @@ -61,9 +62,15 @@ public static Map getConfiguredHeaders(){ e.getValue().unwrapped().toString().replace("{{ngCspNonce}}", ngCspNonceVal) ).append("; ") ); - return Map.of("X-XSS-Protection",headers.getString("X-XSS-Protection"), - "X-Frame-Options",headers.getString("X-Frame-Options"), - "Content-Security-Policy",joined.toString()); + Map headerList = new java.util.HashMap<>(Map.of("X-XSS-Protection", headers.getString("X-XSS-Protection"), + "X-Frame-Options", headers.getString("X-Frame-Options"), + "Content-Security-Policy", joined.toString())); + for(String entry: List.of("X-Content-Type-Options", "Referrer-Policy")) { + if (headers.hasPath(entry) && headers.getString(entry) != null) { + headerList.put(entry, headers.getString(entry)); + } + } + return headerList; } @Override diff --git a/config/defaults/src/main/resources/edu-sharing.reference.conf b/config/defaults/src/main/resources/edu-sharing.reference.conf index efb19240a..0a6404fda 100644 --- a/config/defaults/src/main/resources/edu-sharing.reference.conf +++ b/config/defaults/src/main/resources/edu-sharing.reference.conf @@ -507,6 +507,10 @@ angular { headers: { // enable browser XSS protection (1 is usually the default of browsers) X-XSS-Protection: "1" + // Configure the X-Content-Type-Options, i.e. "nosniff" + X-Content-Type-Options: null + // Configure Referrer-Policy, i.e. "no-referrer" + Referrer-Policy: null // configure allowed ulrs where this edu-sharing ui might be embedded as a frame/embed object X-Frame-Options: "sameorigin" // be careful when modifying these parameters! From 28ceac6ead569a696d9b418bba6ead320bdba52c Mon Sep 17 00:00:00 2001 From: Torsten Simon Date: Wed, 28 Aug 2024 17:01:44 +0200 Subject: [PATCH 2/3] fix:add config for global headers on each request, i.e. for X-Content-Type-Options --- .../repository/server/GlobalHeaderFilter.java | 58 +++++++++++++++++++ .../server/SecurityHeadersFilter.java | 2 +- .../webapp/src/main/webapp/WEB-INF/web.xml | 7 ++- .../main/resources/edu-sharing.reference.conf | 10 +++- 4 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 Backend/services/core/src/main/java/org/edu_sharing/repository/server/GlobalHeaderFilter.java diff --git a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/GlobalHeaderFilter.java b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/GlobalHeaderFilter.java new file mode 100644 index 000000000..5470a752f --- /dev/null +++ b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/GlobalHeaderFilter.java @@ -0,0 +1,58 @@ +package org.edu_sharing.repository.server; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import net.sf.acegisecurity.AuthenticationCredentialsNotFoundException; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.apache.log4j.Logger; +import org.edu_sharing.alfresco.authentication.HttpContext; +import org.edu_sharing.alfresco.authentication.subsystems.SubsystemChainingAuthenticationService; +import org.edu_sharing.alfresco.lightbend.LightbendConfigLoader; +import org.edu_sharing.alfresco.policy.NodeCustomizationPolicies; +import org.edu_sharing.alfresco.repository.server.authentication.Context; +import org.edu_sharing.alfresco.service.config.model.AvailableMds; +import org.edu_sharing.alfresco.workspace_administration.NodeServiceInterceptor; +import org.edu_sharing.alfrescocontext.gate.AlfAppContextGate; +import org.edu_sharing.metadataset.v2.QueryUtils; +import org.edu_sharing.repository.TrackingApplicationInfo; +import org.edu_sharing.repository.client.tools.CCConstants; +import org.edu_sharing.repository.server.tools.ApplicationInfoList; +import org.edu_sharing.repository.server.tools.security.SignatureVerifier; +import org.edu_sharing.restservices.NodeDao; +import org.edu_sharing.restservices.RepositoryDao; +import org.edu_sharing.service.authentication.SSOAuthorityMapper; +import org.edu_sharing.service.authentication.ScopeAuthenticationServiceFactory; +import org.edu_sharing.service.authority.AuthorityServiceFactory; +import org.edu_sharing.service.config.ConfigServiceFactory; +import org.edu_sharing.service.usage.Usage; +import org.edu_sharing.service.usage.Usage2Exception; +import org.edu_sharing.service.usage.Usage2Service; +import org.edu_sharing.webservices.util.AuthenticationUtils; +import org.springframework.context.ApplicationContext; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Map; + + +/** + * Filter to add possible headers that should be included in every request + */ +public class GlobalHeaderFilter implements Filter { + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { + if (LightbendConfigLoader.get().hasPath("security.headers")) { + for (Map.Entry entry : LightbendConfigLoader.get().getObject("security.headers").unwrapped().entrySet()) { + if (entry.getValue() != null) { + ((HttpServletResponse) res).addHeader(entry.getKey(), entry.getValue().toString()); + } + } + } + chain.doFilter(req, res); + } + +} diff --git a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/SecurityHeadersFilter.java b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/SecurityHeadersFilter.java index 40dd652c7..897e56dfe 100644 --- a/Backend/services/core/src/main/java/org/edu_sharing/repository/server/SecurityHeadersFilter.java +++ b/Backend/services/core/src/main/java/org/edu_sharing/repository/server/SecurityHeadersFilter.java @@ -65,7 +65,7 @@ public static Map getConfiguredHeaders(){ Map headerList = new java.util.HashMap<>(Map.of("X-XSS-Protection", headers.getString("X-XSS-Protection"), "X-Frame-Options", headers.getString("X-Frame-Options"), "Content-Security-Policy", joined.toString())); - for(String entry: List.of("X-Content-Type-Options", "Referrer-Policy")) { + for(String entry: List.of("Referrer-Policy")) { if (headers.hasPath(entry) && headers.getString(entry) != null) { headerList.put(entry, headers.getString(entry)); } diff --git a/Backend/services/webapp/src/main/webapp/WEB-INF/web.xml b/Backend/services/webapp/src/main/webapp/WEB-INF/web.xml index c6f49f31b..8981e36b3 100644 --- a/Backend/services/webapp/src/main/webapp/WEB-INF/web.xml +++ b/Backend/services/webapp/src/main/webapp/WEB-INF/web.xml @@ -88,6 +88,11 @@ Edu Context Management Filter org.edu_sharing.repository.server.authentication.ContextManagementFilter + + + Edu Global Header Filter + org.edu_sharing.repository.server.GlobalHeaderFilter + Edu-Sharing Guest Filter @@ -158,7 +163,7 @@ - SameSiteCookieFilter + Edu Global Header Filter /* diff --git a/config/defaults/src/main/resources/edu-sharing.reference.conf b/config/defaults/src/main/resources/edu-sharing.reference.conf index 0a6404fda..757907473 100644 --- a/config/defaults/src/main/resources/edu-sharing.reference.conf +++ b/config/defaults/src/main/resources/edu-sharing.reference.conf @@ -8,6 +8,12 @@ // security and management functions security { + // custom headers that will be included in ANY request, not only index pages but also API etc. + // for frontend / html related headers like csp etc., see the angular part + // headers { + // Configure the X-Content-Type-Options, i.e. "nosniff" + // X-Content-Type-Options: "nosniff" + // } fileManagement { limits: { // max allowed size of files that can be uploaded (in bytes) @@ -507,10 +513,8 @@ angular { headers: { // enable browser XSS protection (1 is usually the default of browsers) X-XSS-Protection: "1" - // Configure the X-Content-Type-Options, i.e. "nosniff" - X-Content-Type-Options: null // Configure Referrer-Policy, i.e. "no-referrer" - Referrer-Policy: null + // Referrer-Policy: "no-referrer" // configure allowed ulrs where this edu-sharing ui might be embedded as a frame/embed object X-Frame-Options: "sameorigin" // be careful when modifying these parameters! From cf5e50ad96e563a69802f592b62283e095165dc7 Mon Sep 17 00:00:00 2001 From: Torsten Simon Date: Wed, 28 Aug 2024 17:36:32 +0200 Subject: [PATCH 3/3] fix:workspace cache mds to improve performance --- .../modules/workspace/workspace.component.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Frontend/src/app/modules/workspace/workspace.component.ts b/Frontend/src/app/modules/workspace/workspace.component.ts index 9ed9503ca..3f09f3ca3 100644 --- a/Frontend/src/app/modules/workspace/workspace.component.ts +++ b/Frontend/src/app/modules/workspace/workspace.component.ts @@ -38,8 +38,6 @@ import { RestConnectorsService, RestConstants, RestHelper, - RestIamService, - RestMdsService, RestNodeService, RestToolService, SessionStorageService, @@ -62,8 +60,8 @@ import { BreadcrumbsService } from '../../shared/components/breadcrumbs/breadcru import { WorkspaceExplorerComponent } from './explorer/explorer.component'; import { WorkspaceTreeComponent } from './tree/tree.component'; import { canDragDrop, canDropOnNode } from './workspace-utils'; -import { UserService } from 'ngx-edu-sharing-api'; -import { mapVCard } from '../../core-module/rest/services/rest-iam.service'; +import { HOME_REPOSITORY, MdsDefinition, MdsService, UserService } from 'ngx-edu-sharing-api'; +import { mapVCard, RestIamService } from '../../core-module/rest/services/rest-iam.service'; import { DialogsService } from '../../features/dialogs/dialogs.service'; import { RecycleMainComponent } from '../node-list/recycle/recycle.component'; @@ -185,7 +183,7 @@ export class WorkspaceMainComponent implements EventListener, OnInit, OnDestroy private toolService: RestToolService, private session: SessionStorageService, private iam: RestIamService, - private mds: RestMdsService, + private mds: MdsService, private node: RestNodeService, private ui: UIService, private event: FrameEventsService, @@ -746,10 +744,13 @@ export class WorkspaceMainComponent implements EventListener, OnInit, OnDestroy this.node.getNodeMetadata(id).subscribe( (data: NodeWrapper) => { this.mds - .getSet( - data.node.metadataset ? data.node.metadataset : RestConstants.DEFAULT, - ) - .subscribe((mds: any) => { + .getMetadataSet({ + repository: HOME_REPOSITORY, + metadataSet: data.node.metadataset + ? data.node.metadataset + : RestConstants.DEFAULT, + }) + .subscribe((mds: MdsDefinition) => { if (mds.create) { this.allowBinary = !mds.create.onlyMetadata; if (!this.allowBinary) {