Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@

import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
Expand All @@ -30,6 +33,7 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
Expand All @@ -40,20 +44,11 @@
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.client.AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.InMemoryReactiveOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.*;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.InMemoryReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.server.AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.server.DefaultServerOAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.client.web.server.ServerAuthorizationRequestRepository;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.server.*;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
Expand All @@ -68,6 +63,7 @@
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.zowe.apiml.config.ApplicationInfo;
import org.zowe.apiml.gateway.config.oidc.ClientConfiguration;
import org.zowe.apiml.gateway.controllers.GatewayExceptionHandler;
import org.zowe.apiml.gateway.filters.proxyheaders.AdditionalRegistrationGatewayRegistry;
Expand All @@ -90,13 +86,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -524,11 +514,12 @@

@Bean
StrictServerWebExchangeFirewall httpFirewall() {
StrictServerWebExchangeFirewall firewall = new StrictServerWebExchangeFirewall();
var strictFirewall = new StrictServerWebExchangeFirewall();
if (isStrictUrlValidationEnabled) {
return firewall;
return strictFirewall;
}

StrictServerWebExchangeFirewall firewall = new ApimlStrictServerWebExchangeFirewall(strictFirewall);
firewall.setAllowUrlEncodedSlash(true);
firewall.setAllowUrlEncodedDoubleSlash(true);
firewall.setAllowBackSlash(true);
Expand All @@ -549,4 +540,71 @@
return new X509AndGwAwareXForwardedHeadersFilter(httpsConfig, trustedProxies, additionalRegistrationGatewayRegistry);
}

@RequiredArgsConstructor
class ApimlStrictServerWebExchangeFirewall extends StrictServerWebExchangeFirewall {

private static final String[] BASE_PATH_MICROSERVICES = {
"/gateway",
"/application",
"/images",
"/v3/api-docs"
};

private static final String[] BASE_PATHS_MODULITH = ArrayUtils.addAll(BASE_PATH_MICROSERVICES, new String[] {
"/discovery",
"/apicatalog",
"/cachingservice"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about zaas and eureka?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zaas is not routable (there is no endpoint). It is valid also for discovery (removed) and eureka is on another port. If these basePath would be used it will be processed as routable (service could have such a serviceId even it is strage)

});

Check warning on line 557 in gateway-service/src/main/java/org/zowe/apiml/gateway/config/WebSecurity.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this array creation and simply pass the elements.

See more on https://sonarcloud.io/project/issues?id=zowe_api-layer&issues=AZ5k0oCKry18d_nOUDoD&open=AZ5k0oCKry18d_nOUDoD&pullRequest=4643

@Value("${server.port}")
private int gatewayPort;

@Autowired

Check warning on line 562 in gateway-service/src/main/java/org/zowe/apiml/gateway/config/WebSecurity.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this field injection and use constructor injection instead.

See more on https://sonarcloud.io/project/issues?id=zowe_api-layer&issues=AZ5k0oCKry18d_nOUDoC&open=AZ5k0oCKry18d_nOUDoC&pullRequest=4643
private ApplicationInfo applicationInfo;

private final StrictServerWebExchangeFirewall nonRoutingFirewall;

boolean isPathToRoute(ServerHttpRequest request, String[] prefixes) {
var path = request.getPath().value();
// homepage
if (Strings.CS.equals(path, "/")) {
return false;
}
for (String prefix : prefixes) {
if (Strings.CS.equals(path, prefix)) {
return false;
}
if (Strings.CS.startsWith(path, prefix + "/")) {
return false;
}
}
return true;
}

boolean isPathToRoute(ServerHttpRequest request) {
if (applicationInfo.isModulith()) {
// check if the request is to DS on the internal port
if (request.getLocalAddress().getPort() != gatewayPort) {
return false;
}

return isPathToRoute(request, BASE_PATHS_MODULITH);
}

return isPathToRoute(request, BASE_PATH_MICROSERVICES);
}


@Override
public Mono<ServerWebExchange> getFirewalledExchange(ServerWebExchange exchange) {
// in case of Gateway and a request to routing use a configured values
if (isPathToRoute(exchange.getRequest())) {
return super.getFirewalledExchange(exchange);
}

return nonRoutingFirewall.getFirewalledExchange(exchange);
}

}

}
Loading