Skip to content

Commit

Permalink
[WIP] Upgrade to Spring Security 5.8
Browse files Browse the repository at this point in the history
  • Loading branch information
Luca Bassi committed Nov 11, 2024
1 parent 937f602 commit 4dcd9da
Show file tree
Hide file tree
Showing 13 changed files with 711 additions and 72 deletions.
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@

<!-- Keep this aligned with the parent project version! -->
<spring-boot.version>2.7.18</spring-boot.version>
<spring-security.version>5.8.15</spring-security.version>

<!-- Sonarcloud.io properties -->
<sonar.projectKey>italiangrid_storm-webdav</sonar.projectKey>
<sonar.organization>italiangrid</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>

<voms-api-java.version>3.3.3</voms-api-java.version>
<milton.version>2.7.1.7</milton.version>
<milton.version>3.1.1.488</milton.version>

<commons-lang.version>2.3</commons-lang.version>
<commons-cli.version>1.2</commons-cli.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,11 +28,11 @@ public class StormMethodSecurityExpressionHandler extends DefaultMethodSecurityE


@Override
public StandardEvaluationContext createEvaluationContextInternal(Authentication authentication,
public EvaluationContext createEvaluationContext(Supplier<Authentication> 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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* 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<RequestAuthorizationContext> {

public static final Logger LOG = LoggerFactory.getLogger(UnanimousDelegatedManager.class);

private final List<AuthorizationManager<RequestAuthorizationContext>> managers;

private final String name;

public ConsensusBasedManager(String name, List<AuthorizationManager<RequestAuthorizationContext>> managers) {
this.name = name;
this.managers = managers;
}

@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {
int grant = 0;
int notGrant = 0;

for (AuthorizationManager<RequestAuthorizationContext> manager : managers) {
AuthorizationDecision result = manager.check(authentication, requestAuthorizationContext);

if (LOG.isDebugEnabled()) {
LOG.debug("Voter: {}, returned: {}", manager, result);
}

if (result == null) {
continue;
} else if (result.isGranted()) {
grant++;
} else {
notGrant++;
}
}

if (grant == 0 && notGrant == 0) {
return new AuthorizationDecision(false);
} else {
return new AuthorizationDecision(grant >= notGrant);
}
}

@Override
public String toString() {
return name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* 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 static org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest.newAuthorizationRequest;

import java.util.function.Supplier;

import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationPdp;
import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties;
import org.italiangrid.storm.webdav.config.StorageAreaInfo;
import org.italiangrid.storm.webdav.server.PathResolver;
import org.italiangrid.storm.webdav.tpc.LocalURLService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;


public class FineGrainedAuthzManager extends PathAuthzPdpManagerSupport {

public static final Logger LOG = LoggerFactory.getLogger(FineGrainedAuthzManager.class);

public FineGrainedAuthzManager(ServiceConfigurationProperties config, PathResolver resolver,
PathAuthorizationPdp pdp, LocalURLService localUrlService) {
super(config, resolver, pdp, localUrlService, true);
}

@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {

final String requestPath = getRequestPath(requestAuthorizationContext.getRequest());
StorageAreaInfo sa = resolver.resolveStorageArea(requestPath);

if (sa == null || !sa.fineGrainedAuthzEnabled()) {
return null;
}

return renderDecision(newAuthorizationRequest(requestAuthorizationContext.getRequest(), authentication.get()), LOG);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* 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 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.function.Supplier;

import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationPdp;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationResult;
import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties;
import org.italiangrid.storm.webdav.config.StorageAreaInfo;
import org.italiangrid.storm.webdav.server.PathResolver;
import org.italiangrid.storm.webdav.tpc.LocalURLService;
import org.italiangrid.storm.webdav.tpc.TransferConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;

public class FineGrainedCopyMoveAuthzManager extends PathAuthzPdpManagerSupport {

public static final Logger LOG = LoggerFactory.getLogger(FineGrainedCopyMoveAuthzManager.class);

public FineGrainedCopyMoveAuthzManager(ServiceConfigurationProperties config, PathResolver resolver,
PathAuthorizationPdp pdp, LocalURLService localUrlService) {
super(config, resolver, pdp, localUrlService, true);
}

@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {

if (!isCopyOrMoveRequest(requestAuthorizationContext.getRequest())) {
return null;
}

String destination = requestAuthorizationContext.getRequest().getHeader(TransferConstants.DESTINATION_HEADER);

if (destination == null) {
return null;
}

if (COPY.name().equals(requestAuthorizationContext.getRequest().getMethod())
&& requestHasRemoteDestinationHeader(requestAuthorizationContext.getRequest(), localUrlService)) {
return null;
}

try {

String destinationPath = getSanitizedPathFromUrl(destination);
StorageAreaInfo sa = resolver.resolveStorageArea(destinationPath);

if (sa == null) {
return null;
}

if (!sa.fineGrainedAuthzEnabled()) {
return null;
}

return renderDecision(PathAuthorizationRequest
.newAuthorizationRequest(requestAuthorizationContext.getRequest(), authentication.get(), destinationPath, PUT),
LOG);

} catch (MalformedURLException e) {
return renderDecision(PathAuthorizationResult.deny(e.getMessage()));
}

}

}
Original file line number Diff line number Diff line change
@@ -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 static com.google.common.base.Strings.isNullOrEmpty;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.function.Supplier;

import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationPdp;
import org.italiangrid.storm.webdav.authz.pdp.PathAuthorizationRequest;
import org.italiangrid.storm.webdav.config.ServiceConfigurationProperties;
import org.italiangrid.storm.webdav.error.StoRMIntializationError;
import org.italiangrid.storm.webdav.oauth.authzserver.jwt.DefaultJwtTokenIssuer;
import org.italiangrid.storm.webdav.server.PathResolver;
import org.italiangrid.storm.webdav.tpc.LocalURLService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.access.intercept.RequestAuthorizationContext;

public class LocalAuthzManager extends PathAuthzPdpManagerSupport {

public static final Logger LOG = LoggerFactory.getLogger(LocalAuthzManager.class);

final URL localTokenIssuer;

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) {
throw new StoRMIntializationError(e.getMessage());
}
}

private boolean isLocalAuthzToken(JwtAuthenticationToken token) {
return localTokenIssuer.equals(token.getToken().getIssuer())
&& !isNullOrEmpty(token.getToken().getClaimAsString(DefaultJwtTokenIssuer.PATH_CLAIM));
}

@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext requestAuthorizationContext) {

if (!(authentication instanceof JwtAuthenticationToken)) {
return null;
}

JwtAuthenticationToken token = (JwtAuthenticationToken) authentication;
if (!isLocalAuthzToken(token)) {
return null;
}

return renderDecision(
PathAuthorizationRequest.newAuthorizationRequest(requestAuthorizationContext.getRequest(), authentication.get()), LOG);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* 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<RequestAuthorizationContext> {

@Override
public AuthorizationDecision check(Supplier<Authentication> 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;
}

}
Loading

0 comments on commit 4dcd9da

Please sign in to comment.