diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index ce3d6572..c8390ec3 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -26,11 +26,11 @@ jobs:
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
steps:
- uses: actions/checkout@v4
- - name: Set up JDK 11
+ - name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
- java-version: 11
+ java-version: 17
- name: Cache Maven packages
uses: actions/cache@v4
with:
diff --git a/Dockerfile b/Dockerfile
index 9d3b7ce3..dce4e616 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
# https://spring.io/guides/topicals/spring-boot-docker#_multi_stage_build
-FROM eclipse-temurin:11-jdk-alpine as build
+FROM eclipse-temurin:17-jdk-alpine as build
WORKDIR /workspace/app
RUN apk add maven
COPY pom.xml .
@@ -11,7 +11,7 @@ COPY src src
RUN mvn package -Dmaven.test.skip
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
-FROM eclipse-temurin:11-centos7
+FROM eclipse-temurin:17-centos7
ENV STORM_WEBDAV_JVM_OPTS="-Dspring.profiles.active=dev"
ARG DEPENDENCY=/workspace/app/target/dependency
diff --git a/README.md b/README.md
index d39889b4..efa56e83 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ The StoRM webdav service provides http/webdav access to resources shared on a fi
You will need:
- git
-- java 11
+- java 17
- maven 3
## Build instructions
diff --git a/pom.xml b/pom.xml
index 71a7e51d..7216044f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,10 +28,11 @@
1.9.0
0.8.8
- 11
+ 17
2.7.18
+ 5.8.15
italiangrid_storm-webdav
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/expression/StormMethodSecurityExpressionHandler.java b/src/main/java/org/italiangrid/storm/webdav/authz/expression/StormMethodSecurityExpressionHandler.java
index 44997ee2..b5196ee0 100644
--- a/src/main/java/org/italiangrid/storm/webdav/authz/expression/StormMethodSecurityExpressionHandler.java
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/expression/StormMethodSecurityExpressionHandler.java
@@ -15,8 +15,10 @@
*/
package org.italiangrid.storm.webdav.authz.expression;
+import java.util.function.Supplier;
+
import org.aopalliance.intercept.MethodInvocation;
-import org.springframework.expression.spel.support.StandardEvaluationContext;
+import org.springframework.expression.EvaluationContext;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
@@ -26,11 +28,11 @@ public class StormMethodSecurityExpressionHandler extends DefaultMethodSecurityE
@Override
- public StandardEvaluationContext createEvaluationContextInternal(Authentication authentication,
+ public EvaluationContext createEvaluationContext(Supplier authentication,
MethodInvocation mi) {
- StandardEvaluationContext ec = super.createEvaluationContextInternal(authentication, mi);
- ec.setVariable("storm", new StormSecurityExpressionMethods(authentication));
+ EvaluationContext ec = super.createEvaluationContext(authentication, mi);
+ ec.setVariable("storm", new StormSecurityExpressionMethods(authentication.get()));
return ec;
}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/ConsensusBasedManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/ConsensusBasedManager.java
new file mode 100644
index 00000000..4533da30
--- /dev/null
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/ConsensusBasedManager.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.italiangrid.storm.webdav.authz.managers;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authorization.AuthorizationDecision;
+import org.springframework.security.authorization.AuthorizationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
+
+public class ConsensusBasedManager implements AuthorizationManager {
+
+ public static final Logger LOG = LoggerFactory.getLogger(ConsensusBasedManager.class);
+
+ private final List> managers;
+
+ private final String name;
+
+ public ConsensusBasedManager(String name,
+ List> managers) {
+ this.name = name;
+ this.managers = managers;
+ }
+
+ @Override
+ public AuthorizationDecision check(Supplier authentication,
+ RequestAuthorizationContext requestAuthorizationContext) {
+ int grant = 0;
+ int notGrant = 0;
+
+ for (AuthorizationManager manager : managers) {
+ AuthorizationDecision result = manager.check(authentication, requestAuthorizationContext);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Voter: {}, returned: {}", manager, result);
+ }
+
+ if (result != null) {
+ if (result.isGranted()) {
+ grant++;
+ } else {
+ notGrant++;
+ }
+ }
+ }
+
+ if (grant == 0 && notGrant == 0) {
+ return new AuthorizationDecision(true);
+ } else {
+ return new AuthorizationDecision(grant >= notGrant);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/voters/FineGrainedAuthzVoter.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedAuthzManager.java
similarity index 64%
rename from src/main/java/org/italiangrid/storm/webdav/authz/voters/FineGrainedAuthzVoter.java
rename to src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedAuthzManager.java
index 3b66ce2a..68039afa 100644
--- a/src/main/java/org/italiangrid/storm/webdav/authz/voters/FineGrainedAuthzVoter.java
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedAuthzManager.java
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.italiangrid.storm.webdav.authz.voters;
+package org.italiangrid.storm.webdav.authz.managers;
import static org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest.newAuthorizationRequest;
-import java.util.Collection;
+import java.util.function.Supplier;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationPdp;
import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties;
@@ -26,32 +26,34 @@
import org.italiangrid.storm.webdav.tpc.LocalURLService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
-import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
-public class FineGrainedAuthzVoter extends PathAuthzPdpVoterSupport {
+public class FineGrainedAuthzManager extends PathAuthzPdpManagerSupport {
- public static final Logger LOG = LoggerFactory.getLogger(FineGrainedAuthzVoter.class);
+ public static final Logger LOG = LoggerFactory.getLogger(FineGrainedAuthzManager.class);
- public FineGrainedAuthzVoter(ServiceConfigurationProperties config, PathResolver resolver,
+ public FineGrainedAuthzManager(ServiceConfigurationProperties config, PathResolver resolver,
PathAuthorizationPdp pdp, LocalURLService localUrlService) {
super(config, resolver, pdp, localUrlService, true);
}
@Override
- public int vote(Authentication authentication, FilterInvocation filter,
- Collection attributes) {
+ public AuthorizationDecision check(Supplier authentication,
+ RequestAuthorizationContext requestAuthorizationContext) {
- final String requestPath = getRequestPath(filter.getHttpRequest());
+ final String requestPath = getRequestPath(requestAuthorizationContext.getRequest());
StorageAreaInfo sa = resolver.resolveStorageArea(requestPath);
if (sa == null || !sa.fineGrainedAuthzEnabled()) {
- return ACCESS_ABSTAIN;
+ return null;
}
- return renderDecision(newAuthorizationRequest(filter.getHttpRequest(), authentication), LOG);
+ return renderDecision(
+ newAuthorizationRequest(requestAuthorizationContext.getRequest(), authentication.get()),
+ LOG);
}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/voters/FineGrainedCopyMoveAuthzVoter.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedCopyMoveAuthzManager.java
similarity index 59%
rename from src/main/java/org/italiangrid/storm/webdav/authz/voters/FineGrainedCopyMoveAuthzVoter.java
rename to src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedCopyMoveAuthzManager.java
index 1de3c859..6e5d4d38 100644
--- a/src/main/java/org/italiangrid/storm/webdav/authz/voters/FineGrainedCopyMoveAuthzVoter.java
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/FineGrainedCopyMoveAuthzManager.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.italiangrid.storm.webdav.authz.voters;
+package org.italiangrid.storm.webdav.authz.managers;
import static org.italiangrid.storm.webdav.server.servlet.WebDAVMethod.COPY;
import static org.italiangrid.storm.webdav.server.servlet.WebDAVMethod.PUT;
import java.net.MalformedURLException;
-import java.util.Collection;
+import java.util.function.Supplier;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationPdp;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest;
@@ -31,36 +31,38 @@
import org.italiangrid.storm.webdav.tpc.TransferConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
-import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
-public class FineGrainedCopyMoveAuthzVoter extends PathAuthzPdpVoterSupport {
+public class FineGrainedCopyMoveAuthzManager extends PathAuthzPdpManagerSupport {
- public static final Logger LOG = LoggerFactory.getLogger(FineGrainedCopyMoveAuthzVoter.class);
+ public static final Logger LOG = LoggerFactory.getLogger(FineGrainedCopyMoveAuthzManager.class);
- public FineGrainedCopyMoveAuthzVoter(ServiceConfigurationProperties config, PathResolver resolver,
- PathAuthorizationPdp pdp, LocalURLService localUrlService) {
+ public FineGrainedCopyMoveAuthzManager(ServiceConfigurationProperties config,
+ PathResolver resolver, PathAuthorizationPdp pdp, LocalURLService localUrlService) {
super(config, resolver, pdp, localUrlService, true);
}
@Override
- public int vote(Authentication authentication, FilterInvocation filter,
- Collection attributes) {
+ public AuthorizationDecision check(Supplier authentication,
+ RequestAuthorizationContext requestAuthorizationContext) {
- if (!isCopyOrMoveRequest(filter.getRequest())) {
- return ACCESS_ABSTAIN;
+ if (!isCopyOrMoveRequest(requestAuthorizationContext.getRequest())) {
+ return null;
}
- String destination = filter.getRequest().getHeader(TransferConstants.DESTINATION_HEADER);
+ String destination =
+ requestAuthorizationContext.getRequest().getHeader(TransferConstants.DESTINATION_HEADER);
if (destination == null) {
- return ACCESS_ABSTAIN;
+ return null;
}
- if (COPY.name().equals(filter.getRequest().getMethod())
- && requestHasRemoteDestinationHeader(filter.getRequest(), localUrlService)) {
- return ACCESS_ABSTAIN;
+ if (COPY.name().equals(requestAuthorizationContext.getRequest().getMethod())
+ && requestHasRemoteDestinationHeader(requestAuthorizationContext.getRequest(),
+ localUrlService)) {
+ return null;
}
try {
@@ -69,15 +71,16 @@ && requestHasRemoteDestinationHeader(filter.getRequest(), localUrlService)) {
StorageAreaInfo sa = resolver.resolveStorageArea(destinationPath);
if (sa == null) {
- return ACCESS_ABSTAIN;
+ return null;
}
if (!sa.fineGrainedAuthzEnabled()) {
- return ACCESS_ABSTAIN;
+ return null;
}
- return renderDecision(PathAuthorizationRequest
- .newAuthorizationRequest(filter.getHttpRequest(), authentication, destinationPath, PUT),
+ return renderDecision(
+ PathAuthorizationRequest.newAuthorizationRequest(requestAuthorizationContext.getRequest(),
+ authentication.get(), destinationPath, PUT),
LOG);
} catch (MalformedURLException e) {
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/voters/LocalAuthzVoter.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/LocalAuthzManager.java
similarity index 61%
rename from src/main/java/org/italiangrid/storm/webdav/authz/voters/LocalAuthzVoter.java
rename to src/main/java/org/italiangrid/storm/webdav/authz/managers/LocalAuthzManager.java
index 1dfdcfca..824a49f2 100644
--- a/src/main/java/org/italiangrid/storm/webdav/authz/voters/LocalAuthzVoter.java
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/LocalAuthzManager.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.italiangrid.storm.webdav.authz.voters;
+package org.italiangrid.storm.webdav.authz.managers;
import static com.google.common.base.Strings.isNullOrEmpty;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collection;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.function.Supplier;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationPdp;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest;
@@ -30,47 +30,52 @@
import org.italiangrid.storm.webdav.tpc.LocalURLService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
-import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
-public class LocalAuthzVoter extends PathAuthzPdpVoterSupport {
+public class LocalAuthzManager extends PathAuthzPdpManagerSupport {
- public static final Logger LOG = LoggerFactory.getLogger(LocalAuthzVoter.class);
+ public static final Logger LOG = LoggerFactory.getLogger(LocalAuthzManager.class);
- final URL localTokenIssuer;
+ final URI localTokenIssuer;
- public LocalAuthzVoter(ServiceConfigurationProperties config, PathResolver resolver,
+ public LocalAuthzManager(ServiceConfigurationProperties config, PathResolver resolver,
PathAuthorizationPdp pdp, LocalURLService localUrlService) {
super(config, resolver, pdp, localUrlService, true);
try {
- localTokenIssuer = new URL(config.getAuthzServer().getIssuer());
- } catch (MalformedURLException e) {
+ localTokenIssuer = new URI(config.getAuthzServer().getIssuer());
+ } catch (URISyntaxException e) {
throw new StoRMIntializationError(e.getMessage());
}
}
private boolean isLocalAuthzToken(JwtAuthenticationToken token) {
- return localTokenIssuer.equals(token.getToken().getIssuer())
+ try {
+ return localTokenIssuer.equals(token.getToken().getIssuer().toURI())
&& !isNullOrEmpty(token.getToken().getClaimAsString(DefaultJwtTokenIssuer.PATH_CLAIM));
+ } catch (URISyntaxException e) {
+ LOG.warn("{}", e.getMessage());
+ return false;
+ }
}
@Override
- public int vote(Authentication authentication, FilterInvocation object,
- Collection attributes) {
+ public AuthorizationDecision check(Supplier authentication,
+ RequestAuthorizationContext requestAuthorizationContext) {
- if (!(authentication instanceof JwtAuthenticationToken)) {
- return ACCESS_ABSTAIN;
+ if (!(authentication.get() instanceof JwtAuthenticationToken)) {
+ return null;
}
- JwtAuthenticationToken token = (JwtAuthenticationToken) authentication;
+ JwtAuthenticationToken token = (JwtAuthenticationToken) authentication.get();
if (!isLocalAuthzToken(token)) {
- return ACCESS_ABSTAIN;
+ return null;
}
- return renderDecision(
- PathAuthorizationRequest.newAuthorizationRequest(object.getRequest(), authentication), LOG);
+ return renderDecision(PathAuthorizationRequest.newAuthorizationRequest(
+ requestAuthorizationContext.getRequest(), authentication.get()), LOG);
}
}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/MacaroonAuthzManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/MacaroonAuthzManager.java
new file mode 100644
index 00000000..9dddb12d
--- /dev/null
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/MacaroonAuthzManager.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.italiangrid.storm.webdav.authz.managers;
+
+import java.util.function.Supplier;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authorization.AuthorizationDecision;
+import org.springframework.security.authorization.AuthorizationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
+import org.springframework.util.Assert;
+
+public class MacaroonAuthzManager implements AuthorizationManager {
+
+ @Override
+ public AuthorizationDecision check(Supplier authentication,
+ RequestAuthorizationContext requestAuthorizationContext) {
+ Assert.notNull(authentication.get(), "authentication must not be null");
+ Assert.notNull(requestAuthorizationContext, "filterInvocation must not be null");
+
+ if (HttpMethod.POST.name().equals(requestAuthorizationContext.getRequest().getMethod())) {
+ return new AuthorizationDecision(true);
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/voters/PathAuthzPdpVoterSupport.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/PathAuthzPdpManagerSupport.java
similarity index 75%
rename from src/main/java/org/italiangrid/storm/webdav/authz/voters/PathAuthzPdpVoterSupport.java
rename to src/main/java/org/italiangrid/storm/webdav/authz/managers/PathAuthzPdpManagerSupport.java
index 4c04911d..03e2b0c5 100644
--- a/src/main/java/org/italiangrid/storm/webdav/authz/voters/PathAuthzPdpVoterSupport.java
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/PathAuthzPdpManagerSupport.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.italiangrid.storm.webdav.authz.voters;
+package org.italiangrid.storm.webdav.authz.managers;
import java.util.EnumSet;
import java.util.Optional;
@@ -28,12 +28,12 @@
import org.italiangrid.storm.webdav.tpc.LocalURLService;
import org.italiangrid.storm.webdav.tpc.TpcUtils;
import org.slf4j.Logger;
-import org.springframework.security.access.AccessDecisionVoter;
-import org.springframework.security.access.ConfigAttribute;
-import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.authorization.AuthorizationDecision;
+import org.springframework.security.authorization.AuthorizationManager;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
-public abstract class PathAuthzPdpVoterSupport
- implements MatcherUtils, TpcUtils, AccessDecisionVoter {
+public abstract class PathAuthzPdpManagerSupport
+ implements MatcherUtils, TpcUtils, AuthorizationManager {
protected static final Set ABSTAIN_DECISIONS =
EnumSet.of(PathAuthorizationResult.Decision.INDETERMINATE,
@@ -45,7 +45,7 @@ public abstract class PathAuthzPdpVoterSupport
protected final LocalURLService localUrlService;
protected final boolean permissive;
- public PathAuthzPdpVoterSupport(ServiceConfigurationProperties config, PathResolver resolver,
+ protected PathAuthzPdpManagerSupport(ServiceConfigurationProperties config, PathResolver resolver,
PathAuthorizationPdp pdp, LocalURLService localUrlService, boolean permissive) {
this.config = config;
this.resolver = resolver;
@@ -54,17 +54,6 @@ public PathAuthzPdpVoterSupport(ServiceConfigurationProperties config, PathResol
this.permissive = permissive;
}
- @Override
- public boolean supports(ConfigAttribute attribute) {
- return false;
- }
-
- @Override
- public boolean supports(Class> clazz) {
- return FilterInvocation.class.isAssignableFrom(clazz);
- }
-
-
protected void logPdpDecision(PathAuthorizationRequest request, PathAuthorizationResult result,
Logger logger) {
String requestString = requestToString(request);
@@ -73,19 +62,19 @@ protected void logPdpDecision(PathAuthorizationRequest request, PathAuthorizatio
result.getPolicy());
}
- public int renderDecision(PathAuthorizationResult result) {
+ public AuthorizationDecision renderDecision(PathAuthorizationResult result) {
if (ABSTAIN_DECISIONS.contains(result.getDecision()) && permissive) {
- return ACCESS_ABSTAIN;
+ return null;
}
if (PathAuthorizationResult.Decision.PERMIT.equals(result.getDecision())) {
- return ACCESS_GRANTED;
+ return new AuthorizationDecision(true);
}
- return ACCESS_DENIED;
+ return new AuthorizationDecision(false);
}
- public int renderDecision(PathAuthorizationRequest request, Logger log) {
+ public AuthorizationDecision renderDecision(PathAuthorizationRequest request, Logger log) {
PathAuthorizationResult result = pdp.authorizeRequest(request);
logPdpDecision(request, result, log);
@@ -93,7 +82,6 @@ public int renderDecision(PathAuthorizationRequest request, Logger log) {
return renderDecision(result);
}
-
public boolean isPermissive() {
return permissive;
}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/managers/UnanimousDelegatedManager.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/UnanimousDelegatedManager.java
new file mode 100644
index 00000000..b5279138
--- /dev/null
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/UnanimousDelegatedManager.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.italiangrid.storm.webdav.authz.managers;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authorization.AuthorizationDecision;
+import org.springframework.security.authorization.AuthorizationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
+
+public class UnanimousDelegatedManager
+ implements AuthorizationManager {
+
+ public static final Logger LOG = LoggerFactory.getLogger(UnanimousDelegatedManager.class);
+
+ private final List> managers;
+
+ private final String name;
+
+ private UnanimousDelegatedManager(String name,
+ List> managers) {
+ this.name = name;
+ this.managers = managers;
+ }
+
+ @Override
+ public AuthorizationDecision check(Supplier authentication,
+ RequestAuthorizationContext filter) {
+ int grant = 0;
+
+ for (AuthorizationManager manager : managers) {
+ AuthorizationDecision result = manager.check(authentication, filter);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Voter: {}, returned: {}", manager, result);
+ }
+
+ if (result != null) {
+ if (result.isGranted()) {
+ grant++;
+ } else {
+ return new AuthorizationDecision(false);
+ }
+ }
+ }
+
+ // To get this far, there were no deny votes
+ if (grant > 0) {
+ return new AuthorizationDecision(true);
+ }
+
+ return null;
+ }
+
+ public static UnanimousDelegatedManager forVoters(String name,
+ List> accessDecisionManagers) {
+ return new UnanimousDelegatedManager(name, accessDecisionManagers);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/voters/WlcgScopeAuthzCopyMoveVoter.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzCopyMoveManager.java
similarity index 61%
rename from src/main/java/org/italiangrid/storm/webdav/authz/voters/WlcgScopeAuthzCopyMoveVoter.java
rename to src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzCopyMoveManager.java
index f1714411..f431743d 100644
--- a/src/main/java/org/italiangrid/storm/webdav/authz/voters/WlcgScopeAuthzCopyMoveVoter.java
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzCopyMoveManager.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.italiangrid.storm.webdav.authz.voters;
+package org.italiangrid.storm.webdav.authz.managers;
import static org.italiangrid.storm.webdav.server.servlet.WebDAVMethod.COPY;
import static org.italiangrid.storm.webdav.server.servlet.WebDAVMethod.PUT;
import java.net.MalformedURLException;
-import java.util.Collection;
+import java.util.function.Supplier;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationPdp;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest;
@@ -31,42 +31,44 @@
import org.italiangrid.storm.webdav.tpc.TransferConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
-import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
-public class WlcgScopeAuthzCopyMoveVoter extends PathAuthzPdpVoterSupport {
+public class WlcgScopeAuthzCopyMoveManager extends PathAuthzPdpManagerSupport {
- public static final Logger LOG = LoggerFactory.getLogger(WlcgScopeAuthzCopyMoveVoter.class);
+ public static final Logger LOG = LoggerFactory.getLogger(WlcgScopeAuthzCopyMoveManager.class);
- public WlcgScopeAuthzCopyMoveVoter(ServiceConfigurationProperties config, PathResolver resolver,
+ public WlcgScopeAuthzCopyMoveManager(ServiceConfigurationProperties config, PathResolver resolver,
PathAuthorizationPdp pdp, LocalURLService localUrlService) {
super(config, resolver, pdp, localUrlService, true);
}
@Override
- public int vote(Authentication authentication, FilterInvocation filter,
- Collection attributes) {
+ public AuthorizationDecision check(Supplier authentication,
+ RequestAuthorizationContext requestAuthorizationContext) {
- if (!(authentication instanceof JwtAuthenticationToken)) {
- return ACCESS_ABSTAIN;
+ if (!(authentication.get() instanceof JwtAuthenticationToken)) {
+ return null;
}
- if (!isCopyOrMoveRequest(filter.getRequest())) {
- return ACCESS_ABSTAIN;
+ if (!isCopyOrMoveRequest(requestAuthorizationContext.getRequest())) {
+ return null;
}
- String destination = filter.getRequest().getHeader(TransferConstants.DESTINATION_HEADER);
+ String destination =
+ requestAuthorizationContext.getRequest().getHeader(TransferConstants.DESTINATION_HEADER);
if (destination == null) {
- return ACCESS_ABSTAIN;
+ return null;
}
- if (COPY.name().equals(filter.getRequest().getMethod())
- && requestHasRemoteDestinationHeader(filter.getRequest(), localUrlService)) {
- return ACCESS_ABSTAIN;
+ if (COPY.name().equals(requestAuthorizationContext.getRequest().getMethod())
+ && requestHasRemoteDestinationHeader(requestAuthorizationContext.getRequest(),
+ localUrlService)) {
+ return null;
}
try {
@@ -75,16 +77,16 @@ && requestHasRemoteDestinationHeader(filter.getRequest(), localUrlService)) {
StorageAreaInfo sa = resolver.resolveStorageArea(destinationPath);
if (sa == null) {
- return ACCESS_ABSTAIN;
+ return null;
}
if (!sa.wlcgScopeAuthzEnabled()) {
- return ACCESS_ABSTAIN;
+ return null;
}
- return renderDecision(PathAuthorizationRequest
- .newAuthorizationRequest(filter.getHttpRequest(), authentication, destinationPath,
- PUT),
+ return renderDecision(
+ PathAuthorizationRequest.newAuthorizationRequest(requestAuthorizationContext.getRequest(),
+ authentication.get(), destinationPath, PUT),
LOG);
} catch (MalformedURLException e) {
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/voters/WlcgScopeAuthzVoter.java b/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzManager.java
similarity index 63%
rename from src/main/java/org/italiangrid/storm/webdav/authz/voters/WlcgScopeAuthzVoter.java
rename to src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzManager.java
index 5da7658a..36e0c2e5 100644
--- a/src/main/java/org/italiangrid/storm/webdav/authz/voters/WlcgScopeAuthzVoter.java
+++ b/src/main/java/org/italiangrid/storm/webdav/authz/managers/WlcgScopeAuthzManager.java
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.italiangrid.storm.webdav.authz.voters;
+package org.italiangrid.storm.webdav.authz.managers;
import static org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest.newAuthorizationRequest;
-import java.util.Collection;
+import java.util.function.Supplier;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationPdp;
import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties;
@@ -26,41 +26,43 @@
import org.italiangrid.storm.webdav.tpc.LocalURLService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
-import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
-public class WlcgScopeAuthzVoter extends PathAuthzPdpVoterSupport {
+public class WlcgScopeAuthzManager extends PathAuthzPdpManagerSupport {
- public static final Logger LOG = LoggerFactory.getLogger(WlcgScopeAuthzVoter.class);
+ public static final Logger LOG = LoggerFactory.getLogger(WlcgScopeAuthzManager.class);
- public WlcgScopeAuthzVoter(ServiceConfigurationProperties config, PathResolver resolver,
+ public WlcgScopeAuthzManager(ServiceConfigurationProperties config, PathResolver resolver,
PathAuthorizationPdp pdp, LocalURLService localUrlService) {
super(config, resolver, pdp, localUrlService, true);
}
@Override
- public int vote(Authentication authentication, FilterInvocation filter,
- Collection attributes) {
+ public AuthorizationDecision check(Supplier authentication,
+ RequestAuthorizationContext requestAuthorizationContext) {
- if (!(authentication instanceof JwtAuthenticationToken)) {
- return ACCESS_ABSTAIN;
+ if (!(authentication.get() instanceof JwtAuthenticationToken)) {
+ return null;
}
- final String requestPath = getRequestPath(filter.getHttpRequest());
+ final String requestPath = getRequestPath(requestAuthorizationContext.getRequest());
StorageAreaInfo sa = resolver.resolveStorageArea(requestPath);
if (sa == null) {
- return ACCESS_ABSTAIN;
+ return null;
}
if (!sa.wlcgScopeAuthzEnabled()) {
- return ACCESS_ABSTAIN;
+ return null;
}
- return renderDecision(newAuthorizationRequest(filter.getHttpRequest(), authentication), LOG);
+ return renderDecision(
+ newAuthorizationRequest(requestAuthorizationContext.getRequest(), authentication.get()),
+ LOG);
}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/voters/MacaroonAuthzVoter.java b/src/main/java/org/italiangrid/storm/webdav/authz/voters/MacaroonAuthzVoter.java
deleted file mode 100644
index c8c0a69b..00000000
--- a/src/main/java/org/italiangrid/storm/webdav/authz/voters/MacaroonAuthzVoter.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.italiangrid.storm.webdav.authz.voters;
-
-import java.util.Collection;
-
-import org.springframework.http.HttpMethod;
-import org.springframework.security.access.AccessDecisionVoter;
-import org.springframework.security.access.ConfigAttribute;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.web.FilterInvocation;
-import org.springframework.util.Assert;
-
-public class MacaroonAuthzVoter implements AccessDecisionVoter {
-
- @Override
- public boolean supports(ConfigAttribute attribute) {
- return true;
- }
-
- @Override
- public boolean supports(Class> clazz) {
- return true;
- }
-
- @Override
- public int vote(Authentication authentication, FilterInvocation filterInvocation,
- Collection attributes) {
- Assert.notNull(authentication, "authentication must not be null");
- Assert.notNull(filterInvocation, "filterInvocation must not be null");
-
- if (HttpMethod.POST.name().equals(filterInvocation.getHttpRequest().getMethod())) {
- return ACCESS_GRANTED;
- }
- return ACCESS_ABSTAIN;
- }
-
-}
diff --git a/src/main/java/org/italiangrid/storm/webdav/authz/voters/UnanimousDelegatedVoter.java b/src/main/java/org/italiangrid/storm/webdav/authz/voters/UnanimousDelegatedVoter.java
deleted file mode 100644
index 5ef66557..00000000
--- a/src/main/java/org/italiangrid/storm/webdav/authz/voters/UnanimousDelegatedVoter.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.italiangrid.storm.webdav.authz.voters;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.access.AccessDecisionVoter;
-import org.springframework.security.access.ConfigAttribute;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.web.FilterInvocation;
-
-public class UnanimousDelegatedVoter implements AccessDecisionVoter {
-
- public static final Logger LOG = LoggerFactory.getLogger(UnanimousDelegatedVoter.class);
-
- private final List> voters;
-
- private final String name;
-
- private UnanimousDelegatedVoter(String name, List> voters) {
- this.name = name;
- this.voters = voters;
- }
-
- @Override
- public boolean supports(ConfigAttribute attribute) {
- return false;
- }
-
- @Override
- public boolean supports(Class> clazz) {
- return FilterInvocation.class.isAssignableFrom(clazz);
- }
-
- @Override
- public int vote(Authentication authentication, FilterInvocation filter,
- Collection attributes) {
-
- int grant = 0;
-
- List singleAttributeList = new ArrayList<>(1);
- singleAttributeList.add(null);
-
- for (ConfigAttribute attribute : attributes) {
- singleAttributeList.set(0, attribute);
-
- for (AccessDecisionVoter voter : voters) {
- int result = voter.vote(authentication, filter, singleAttributeList);
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Voter: {}, returned: {}", voter, result);
- }
-
- switch (result) {
- case AccessDecisionVoter.ACCESS_GRANTED:
- grant++;
-
- break;
-
- case AccessDecisionVoter.ACCESS_DENIED:
- return AccessDecisionVoter.ACCESS_DENIED;
-
- default:
- break;
- }
- }
- }
-
- // To get this far, there were no deny votes
- if (grant > 0) {
- return AccessDecisionVoter.ACCESS_GRANTED;
- }
-
-
- return AccessDecisionVoter.ACCESS_ABSTAIN;
- }
-
- public static UnanimousDelegatedVoter forVoters(String name,
- List> accessDecisionVoters) {
- return new UnanimousDelegatedVoter(name, accessDecisionVoters);
- }
-
- @Override
- public String toString() {
- return name;
- }
-}
diff --git a/src/main/java/org/italiangrid/storm/webdav/spring/web/SecurityConfig.java b/src/main/java/org/italiangrid/storm/webdav/spring/web/SecurityConfig.java
index 0e85dbf0..dcb93070 100644
--- a/src/main/java/org/italiangrid/storm/webdav/spring/web/SecurityConfig.java
+++ b/src/main/java/org/italiangrid/storm/webdav/spring/web/SecurityConfig.java
@@ -16,7 +16,7 @@
package org.italiangrid.storm.webdav.spring.web;
import static java.util.Arrays.asList;
-import static org.italiangrid.storm.webdav.authz.voters.UnanimousDelegatedVoter.forVoters;
+import static org.italiangrid.storm.webdav.authz.managers.UnanimousDelegatedManager.forVoters;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED;
@@ -41,13 +41,14 @@
import org.italiangrid.storm.webdav.authz.pdp.WlcgStructuredPathAuthorizationPdp;
import org.italiangrid.storm.webdav.authz.util.ReadonlyHttpMethodMatcher;
import org.italiangrid.storm.webdav.authz.util.SaveAuthnAccessDeniedHandler;
-import org.italiangrid.storm.webdav.authz.voters.FineGrainedAuthzVoter;
-import org.italiangrid.storm.webdav.authz.voters.FineGrainedCopyMoveAuthzVoter;
-import org.italiangrid.storm.webdav.authz.voters.LocalAuthzVoter;
-import org.italiangrid.storm.webdav.authz.voters.MacaroonAuthzVoter;
-import org.italiangrid.storm.webdav.authz.voters.UnanimousDelegatedVoter;
-import org.italiangrid.storm.webdav.authz.voters.WlcgScopeAuthzCopyMoveVoter;
-import org.italiangrid.storm.webdav.authz.voters.WlcgScopeAuthzVoter;
+import org.italiangrid.storm.webdav.authz.managers.ConsensusBasedManager;
+import org.italiangrid.storm.webdav.authz.managers.FineGrainedAuthzManager;
+import org.italiangrid.storm.webdav.authz.managers.FineGrainedCopyMoveAuthzManager;
+import org.italiangrid.storm.webdav.authz.managers.LocalAuthzManager;
+import org.italiangrid.storm.webdav.authz.managers.MacaroonAuthzManager;
+import org.italiangrid.storm.webdav.authz.managers.UnanimousDelegatedManager;
+import org.italiangrid.storm.webdav.authz.managers.WlcgScopeAuthzCopyMoveManager;
+import org.italiangrid.storm.webdav.authz.managers.WlcgScopeAuthzManager;
import org.italiangrid.storm.webdav.config.OAuthProperties;
import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties;
import org.italiangrid.storm.webdav.config.StorageAreaConfiguration;
@@ -65,24 +66,26 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
-import org.springframework.security.access.AccessDecisionManager;
-import org.springframework.security.access.AccessDecisionVoter;
-import org.springframework.security.access.vote.ConsensusBased;
import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.authorization.AuthorizationManager;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
+import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.HstsConfig;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
-import org.springframework.security.web.access.expression.WebExpressionVoter;
+import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
+import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.RequestRejectedException;
import org.springframework.security.web.firewall.RequestRejectedHandler;
import org.springframework.security.web.firewall.StrictHttpFirewall;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.google.common.collect.Lists;
@Configuration
+@EnableMethodSecurity(proxyTargetClass = true)
public class SecurityConfig {
private static final Logger LOG = LoggerFactory.getLogger(SecurityConfig.class);
@@ -148,51 +151,65 @@ SecurityFilterChain filterChain(HttpSecurity http, VOMSAuthenticationProvider vo
if (serviceConfigurationProperties.getAuthz().isDisabled()) {
LOG.warn("AUTHORIZATION DISABLED: this shouldn't be used in production!");
- http.authorizeRequests().anyRequest().permitAll();
+ http.authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll());
} else {
- http.authorizeRequests().accessDecisionManager(fineGrainedAccessDecisionManager());
addAccessRules(http);
addAnonymousAccessRules(http);
}
if (serviceConfigurationProperties.getRedirector().isEnabled()) {
- http.headers().httpStrictTransportSecurity().disable();
+ http.headers(headers -> headers.httpStrictTransportSecurity(HstsConfig::disable));
}
- http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(authConverter);
-
- http.authorizeRequests().antMatchers("/errors/**").permitAll();
-
- http.authorizeRequests()
- .antMatchers(HttpMethod.GET, "/.well-known/oauth-authorization-server",
- "/.well-known/openid-configuration", "/.well-known/wlcg-tape-rest-api")
- .permitAll();
+ http.oauth2ResourceServer(
+ oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(authConverter)));
+
+ http.authorizeHttpRequests(
+ authorize -> authorize.requestMatchers(AntPathRequestMatcher.antMatcher("/errors/**"))
+ .permitAll());
+
+ http.authorizeHttpRequests(authorize -> authorize
+ .requestMatchers(
+ AntPathRequestMatcher.antMatcher(HttpMethod.GET,
+ "/.well-known/oauth-authorization-server"),
+ AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/.well-known/openid-configuration"),
+ AntPathRequestMatcher.antMatcher(HttpMethod.GET, "/.well-known/wlcg-tape-rest-api"))
+ .permitAll());
+
+ http.authorizeHttpRequests(
+ authorize -> authorize
+ .requestMatchers(AntPathRequestMatcher.antMatcher("/css/*"),
+ AntPathRequestMatcher.antMatcher("/js/*"))
+ .permitAll());
+
+ if (!serviceConfigurationProperties.getAuthz().isDisabled()) {
+ http.authorizeHttpRequests(
+ authorize -> authorize.anyRequest().access(fineGrainedAuthorizationManager(null)));
+ }
AccessDeniedHandlerImpl handler = new AccessDeniedHandlerImpl();
handler.setErrorPage("/errors/403");
- http.exceptionHandling()
- .accessDeniedHandler(new SaveAuthnAccessDeniedHandler(principalHelper, handler));
+ http.exceptionHandling(exception -> exception
+ .accessDeniedHandler(new SaveAuthnAccessDeniedHandler(principalHelper, handler)));
- http.logout()
- .logoutUrl("/logout")
+ http.logout(logout -> logout.logoutUrl("/logout")
.clearAuthentication(true)
.invalidateHttpSession(true)
- .logoutSuccessUrl("/");
+ .logoutSuccessUrl("/"));
if (!oauthProperties.isEnableOidc()) {
- http.exceptionHandling().authenticationEntryPoint(new ErrorPageAuthenticationEntryPoint());
+ http.exceptionHandling(
+ exception -> exception.authenticationEntryPoint(new ErrorPageAuthenticationEntryPoint()));
}
configureOidcAuthn(http);
- http.csrf().disable();
- http.cors().disable();
+ http.csrf(csrf -> csrf.disable());
+ http.cors(cors -> cors.disable());
return http.build();
}
-
-
@Bean
static ErrorPageRegistrar securityErrorPageRegistrar() {
return r -> {
@@ -206,11 +223,6 @@ static ErrorPageRegistrar securityErrorPageRegistrar() {
};
}
- @Bean
- WebSecurityCustomizer webSecurityCustomizer() {
- return web -> web.ignoring().antMatchers("/css/*", "/js/*");
- }
-
@Bean
RequestRejectedHandler requestRejectedHandler() {
return new HttpMethodRequestRejectedHandler(ALLOWED_METHODS);
@@ -226,13 +238,13 @@ protected void addAnonymousAccessRules(HttpSecurity http) throws Exception {
}
if (!anonymousAccessPermissions.isEmpty()) {
- http.anonymous().authorities(anonymousAccessPermissions);
+ http.anonymous(anonymous -> anonymous.authorities(anonymousAccessPermissions));
}
}
protected void configureOidcAuthn(HttpSecurity http) throws Exception {
if (oauthProperties.isEnableOidc()) {
- http.oauth2Login().loginPage("/oidc-login");
+ http.oauth2Login(oauth2Login -> oauth2Login.loginPage("/oidc-login"));
}
}
@@ -251,45 +263,56 @@ protected void addAccessRules(HttpSecurity http) throws Exception {
String readAccessRule =
String.format("hasAuthority('%s')", SAPermission.canRead(sa).getAuthority());
LOG.debug("Read access rule: {}", readAccessRule);
- http.authorizeRequests()
- .requestMatchers(new ReadonlyHttpMethodMatcher(ap + "/**"))
- .access(readAccessRule);
-
- http.authorizeRequests().antMatchers(ap + "/**").access(writeAccessRule);
+ http.authorizeHttpRequests(
+ authorize -> authorize.requestMatchers(new ReadonlyHttpMethodMatcher(ap + "/**"))
+ .access(fineGrainedAuthorizationManager(
+ new WebExpressionAuthorizationManager(readAccessRule))));
+
+ http.authorizeHttpRequests(
+ authorize -> authorize.requestMatchers(AntPathRequestMatcher.antMatcher(ap + "/**"))
+ .access(fineGrainedAuthorizationManager(
+ new WebExpressionAuthorizationManager(writeAccessRule))));
}
}
- protected AccessDecisionManager fineGrainedAccessDecisionManager() throws MalformedURLException {
- List> voters = new ArrayList<>();
+ protected AuthorizationManager fineGrainedAuthorizationManager(
+ WebExpressionAuthorizationManager webExpressionAuthorizationManager) {
+ List> voters = new ArrayList<>();
- UnanimousDelegatedVoter fineGrainedVoters = forVoters("FineGrainedAuthz",
+ UnanimousDelegatedManager fineGrainedVoters = forVoters("FineGrainedAuthz",
asList(
- new FineGrainedAuthzVoter(serviceConfigurationProperties, pathResolver,
+ new FineGrainedAuthzManager(serviceConfigurationProperties, pathResolver,
fineGrainedAuthzPdp, localURLService),
- new FineGrainedCopyMoveAuthzVoter(serviceConfigurationProperties, pathResolver,
+ new FineGrainedCopyMoveAuthzManager(serviceConfigurationProperties, pathResolver,
fineGrainedAuthzPdp, localURLService)));
WlcgStructuredPathAuthorizationPdp wlcgPdp = new WlcgStructuredPathAuthorizationPdp(
serviceConfigurationProperties, pathResolver, localURLService);
- UnanimousDelegatedVoter wlcgVoters = forVoters("WLCGScopeBasedAuthz",
+ UnanimousDelegatedManager wlcgVoters = forVoters("WLCGScopeBasedAuthz",
asList(
- new WlcgScopeAuthzVoter(serviceConfigurationProperties, pathResolver, wlcgPdp,
+ new WlcgScopeAuthzManager(serviceConfigurationProperties, pathResolver, wlcgPdp,
localURLService),
- new WlcgScopeAuthzCopyMoveVoter(serviceConfigurationProperties, pathResolver, wlcgPdp,
+ new WlcgScopeAuthzCopyMoveManager(serviceConfigurationProperties, pathResolver, wlcgPdp,
localURLService)));
if (serviceConfigurationProperties.getRedirector().isEnabled()) {
- voters.add(new LocalAuthzVoter(serviceConfigurationProperties, pathResolver,
- new LocalAuthorizationPdp(serviceConfigurationProperties), localURLService));
+ try {
+ voters.add(new LocalAuthzManager(serviceConfigurationProperties, pathResolver,
+ new LocalAuthorizationPdp(serviceConfigurationProperties), localURLService));
+ } catch (MalformedURLException e) {
+ LOG.error(e.getMessage(), e);
+ }
}
if (serviceConfigurationProperties.getAuthzServer().isEnabled()
&& serviceConfigurationProperties.getMacaroonFilter().isEnabled()) {
- voters.add(new MacaroonAuthzVoter());
+ voters.add(new MacaroonAuthzManager());
+ }
+ if (webExpressionAuthorizationManager != null) {
+ voters.add(webExpressionAuthorizationManager);
}
- voters.add(new WebExpressionVoter());
voters.add(fineGrainedVoters);
voters.add(wlcgVoters);
- return new ConsensusBased(voters);
+ return new ConsensusBasedManager("Consensus", voters);
}
}
diff --git a/src/main/java/org/italiangrid/storm/webdav/spring/web/SecurityExpressionHandlerConfiguration.java b/src/main/java/org/italiangrid/storm/webdav/spring/web/SecurityExpressionHandlerConfiguration.java
deleted file mode 100644
index c4701882..00000000
--- a/src/main/java/org/italiangrid/storm/webdav/spring/web/SecurityExpressionHandlerConfiguration.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright (c) Istituto Nazionale di Fisica Nucleare, 2014-2023.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.italiangrid.storm.webdav.spring.web;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
-import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
-import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
-
-@Configuration
-@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
-public class SecurityExpressionHandlerConfiguration extends GlobalMethodSecurityConfiguration {
-
- @Override
- protected MethodSecurityExpressionHandler createExpressionHandler() {
- return new DefaultMethodSecurityExpressionHandler();
- }
-
-}