Skip to content

Commit

Permalink
Merge branch 'release/1.0.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
LEDfan committed Jul 25, 2023
2 parents c835240 + a1289a6 commit 2c71c88
Show file tree
Hide file tree
Showing 31 changed files with 523 additions and 331 deletions.
14 changes: 9 additions & 5 deletions .github/workflows/workflows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ jobs:
kubernetes:
- 'v1.21.6'
- 'v1.22.17'
- 'v1.23.15'
- 'v1.24.9'
- 'v1.25.5'
- 'v1.23.17'
- 'v1.24.15'
- 'v1.25.11'
- 'v1.26.6'
- 'v1.27.3'

steps:
- uses: actions/checkout@v2
Expand All @@ -32,9 +34,11 @@ jobs:
- name: Setup Minikube
uses: manusa/actions-setup-minikube@v2.7.2
with:
minikube version: 'v1.28.0'
minikube version: 'v1.30.1'
kubernetes version: ${{ matrix.kubernetes }}
github token: ${{ secrets.GITHUB_TOKEN }}
container runtime: containerd
driver: docker
- name: Setup Docker
run: sudo apt-get -qq -y install conntrack socat ; nohup socat TCP-LISTEN:2375,reuseaddr,fork UNIX-CONNECT:/var/run/docker.sock &
- name: Setup Docker Swarm
Expand All @@ -52,7 +56,7 @@ jobs:
docker ps -a
kubectl get pod -A
- name: Run Tests
run: mvn -B test
run: mvn -B test

dependency:
runs-on: ubuntu-latest
Expand Down
12 changes: 3 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>eu.openanalytics</groupId>
<artifactId>containerproxy</artifactId>
<version>1.0.1</version>
<version>1.0.2</version>
<name>ContainerProxy</name>
<packaging>jar</packaging>

Expand Down Expand Up @@ -59,14 +59,8 @@
<url>https://clojars.org/repo/</url>
</repository>
<repository>
<!-- Currently used only for the opensaml dependency -->
<id>shibboleth</id>
<url>https://build.shibboleth.net/nexus/content/repositories/releases/</url>
</repository>
<repository>
<!-- Currently used only for the spring-social-github 1.0.0.M4 dependency -->
<id>spring</id>
<url>https://repo.spring.io/plugins-release/</url>
<id>oa-nexus-releases</id>
<url>https://nexus.openanalytics.eu/repository/releases</url>
</repository>
</repositories>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.health.Health;
Expand Down Expand Up @@ -71,12 +72,17 @@
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Security;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Executor;

import static eu.openanalytics.containerproxy.api.ApiSecurityService.PROP_API_SECURITY_HIDE_SPEC_DETAILS;
import static eu.openanalytics.containerproxy.service.AppRecoveryService.PROPERTY_RECOVER_RUNNING_PROXIES;
import static eu.openanalytics.containerproxy.service.AppRecoveryService.PROPERTY_RECOVER_RUNNING_PROXIES_FROM_DIFFERENT_CONFIG;
import static eu.openanalytics.containerproxy.service.ProxyService.PROPERTY_STOP_PROXIES_ON_SHUTDOWN;

@EnableScheduling
Expand Down Expand Up @@ -119,7 +125,11 @@ public static void main(String[] args) {
app.addListeners(new LoggingConfigurer());

boolean hasExternalConfig = Files.exists(Paths.get(CONFIG_FILENAME));
if (!hasExternalConfig) app.setAdditionalProfiles(CONFIG_DEMO_PROFILE);
if (!hasExternalConfig) {
app.setAdditionalProfiles(CONFIG_DEMO_PROFILE);
Logger log = LogManager.getLogger(ContainerProxyApplication.class);
log.warn("WARNING: Did not found configuration, using fallback configuration!");
}

setDefaultProperties(app);

Expand Down Expand Up @@ -152,7 +162,6 @@ public void init() {
log.warn("WARNING: Invalid configuration detected: same-site-cookie policy is set to None, but secure-cookies are not enabled. Secure cookies must be enabled when using None as same-site-cookie policy ");
}


if (environment.getProperty("proxy.store-mode", "").equalsIgnoreCase("Redis")) {
if (!environment.getProperty("spring.session.store-type", "").equalsIgnoreCase("redis")) {
// running in HA mode, but not using Redis sessions
Expand All @@ -162,6 +171,24 @@ public void init() {
// running in HA mode, but proxies are removed when shutting down
log.warn("WARNING: Invalid configuration detected: store-mode is set to Redis (i.e. High-Availability mode), but proxies are stopped at shutdown of server!");
}
if (environment.getProperty( PROPERTY_RECOVER_RUNNING_PROXIES, Boolean.class, false) ||
environment.getProperty( PROPERTY_RECOVER_RUNNING_PROXIES_FROM_DIFFERENT_CONFIG, Boolean.class, false) ) {
log.warn("WARNING: Invalid configuration detected: cannot use store-mode with Redis (i.e. High-Availability mode) and app recovery at the same time. Disable app recovery!");
}
}

if (environment.getProperty("spring.session.store-type", "").equalsIgnoreCase("redis")) {
if (!environment.getProperty("proxy.store-mode", "").equalsIgnoreCase("Redis")) {
// using Redis sessions, but not running in HA mode -> this does not make sense
// even with one replica, the HA mode should be used in order for the server to survive restarts (which is the reason Redis sessions are used)
log.warn("WARNING: Invalid configuration detected: user sessions are stored in Redis, but store-more is not set to Redis. Change store-mode so that app sessions are stored in Redis!");
}
if (environment.getProperty( PROPERTY_RECOVER_RUNNING_PROXIES, Boolean.class, false) ||
environment.getProperty( PROPERTY_RECOVER_RUNNING_PROXIES_FROM_DIFFERENT_CONFIG, Boolean.class, false) ) {
// using Redis sessions together with app recovery -> this does not make sense
// if already using Redis for sessions there is no reason to not store app sessions
log.warn("WARNING: Invalid configuration detected: user sessions are stored in Redis and App Recovery is enabled. Instead of using App Recovery, change store-mode so that app sessions are stored in Redis!");
}
}

boolean hideSpecDetails = environment.getProperty(PROP_API_SECURITY_HIDE_SPEC_DETAILS, Boolean.class, true);
Expand Down Expand Up @@ -345,4 +372,24 @@ private static void setDefaultProperties(SpringApplication app) {
System.setProperty("jdk.serialSetFilterAfterRead", "true");
}

@Bean
public GroupedOpenApi groupOpenApi() {
return GroupedOpenApi.builder()
.group("v1")
.addOpenApiCustomiser(openApi -> {
Set<String> endpoints = new HashSet<>(Arrays.asList("/app_direct_i/**", "/app_direct/**", "/app_proxy/{proxyId}/**", "/error"));
openApi.getPaths().entrySet().stream().filter(p -> endpoints.contains(p.getKey()))
.forEach(p -> {
p.getValue().setHead(null);
p.getValue().setPost(null);
p.getValue().setDelete(null);
p.getValue().setParameters(null);
p.getValue().setOptions(null);
p.getValue().setPut(null);
p.getValue().setPatch(null);
});
})
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import eu.openanalytics.containerproxy.model.runtime.Proxy;
import eu.openanalytics.containerproxy.service.ProxyService;
import eu.openanalytics.containerproxy.service.UserService;
import eu.openanalytics.containerproxy.util.ImmediateJsonResponse;
import eu.openanalytics.containerproxy.util.ProxyMappingManager;
import eu.openanalytics.containerproxy.util.ContextPathHelper;
import org.springframework.stereotype.Controller;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ public class ProxyStatusController {
mediaType = "application/json",
schema = @Schema(implementation = ChangeProxyStatusDto.class),
examples = {
@ExampleObject(name = "Stopping", description = "Stop a proxy.", value = "{\"desiredStatus\": \"Stopping\"}"),
@ExampleObject(name = "Pausing", description = "Pause a proxy.", value = "{\"desiredStatus\": \"Pausing\"}"),
@ExampleObject(name = "Resuming", description = "Resume a proxy.", value = "{\"desiredStatus\": \"Resuming\"}"),
@ExampleObject(name = "Resuming with parameters", description = "Resume a proxy.", value = "{\"desiredStatus\": \"Resuming\", \"parameters\":{\"resources\":\"2 CPU cores - 8G RAM\",\"other_parameter\":\"example\"}}")
@ExampleObject(name = "Stopping", description = "Stop a proxy.", value = "{\"desiredState\": \"Stopping\"}"),
@ExampleObject(name = "Pausing", description = "Pause a proxy.", value = "{\"desiredState\": \"Pausing\"}"),
@ExampleObject(name = "Resuming", description = "Resume a proxy.", value = "{\"desiredState\": \"Resuming\"}"),
@ExampleObject(name = "Resuming with parameters", description = "Resume a proxy.", value = "{\"desiredState\": \"Resuming\", \"parameters\":{\"resources\":\"2 CPU cores - 8G RAM\",\"other_parameter\":\"example\"}}")
}
)
)
Expand Down Expand Up @@ -140,15 +140,12 @@ public ResponseEntity<ApiResponse<Void>> changeProxyStatus(@PathVariable String
return ApiResponse.fail(ex.getMessage());
}
} else if (changeProxyStateDto.getDesiredState().equals("Stopping")) {
if (!proxy.getStatus().equals(ProxyStatus.New)
&& !proxy.getStatus().equals(ProxyStatus.Up)
&& !proxy.getStatus().equals(ProxyStatus.Resuming)
&& !proxy.getStatus().equals(ProxyStatus.Paused)) {
return ApiResponse.fail(String.format("Cannot stop proxy because it is not in New, Up or Paused status (status is %s)", proxy.getStatus()));
if (proxy.getStatus().equals(ProxyStatus.Stopped)) {
return ApiResponse.fail("Cannot stop proxy because it is already stopped");
}
asyncProxyService.stopProxy(proxy, false);
} else {
return ApiResponse.fail("Invalid desiredStatus");
return ApiResponse.fail("Invalid desiredState");
}

return ApiResponse.success();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy;
import org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy;
Expand Down Expand Up @@ -92,6 +92,10 @@ public class KeycloakAuthenticationBackend implements IAuthenticationBackend {
@Lazy
AuthenticationManager authenticationManager;

@Inject
@Lazy
private SavedRequestAwareAuthenticationSuccessHandler successHandler;

@Override
public String getName() {
return NAME;
Expand Down Expand Up @@ -142,9 +146,7 @@ protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessin
KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(authenticationManager, requestMatcher);
filter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy());
filter.setAuthenticationFailureHandler(keycloakAuthenticationFailureHandler());
SimpleUrlAuthenticationSuccessHandler handler = new SimpleUrlAuthenticationSuccessHandler("/");
handler.setAlwaysUseDefaultTargetUrl(true);
filter.setAuthenticationSuccessHandler(handler);
filter.setAuthenticationSuccessHandler(successHandler);
// Fix: call afterPropertiesSet manually, because Spring doesn't invoke it for some reason.
filter.setApplicationContext(ctx);
filter.afterPropertiesSet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand Down Expand Up @@ -58,6 +59,7 @@
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
Expand Down Expand Up @@ -92,6 +94,10 @@ public class OpenIDAuthenticationBackend implements IAuthenticationBackend {
@Inject
private ClientRegistrationRepository clientRegistrationRepo;

@Inject
@Lazy
private SavedRequestAwareAuthenticationSuccessHandler successHandler;

private static OAuth2AuthorizedClientService oAuth2AuthorizedClientService;

@Autowired
Expand All @@ -115,11 +121,11 @@ public boolean hasAuthorization() {
@Override
public void configureHttpSecurity(HttpSecurity http, AuthorizedUrl anyRequestConfigurer) throws Exception {
anyRequestConfigurer.authenticated();

http
.oauth2Login()
.loginPage("/login")
.defaultSuccessUrl("/", true)
.successHandler(successHandler)
.clientRegistrationRepository(clientRegistrationRepo)
.authorizedClientService(oAuth2AuthorizedClientService)
.authorizationEndpoint()
Expand All @@ -140,7 +146,7 @@ public void onAuthenticationFailure(HttpServletRequest request, HttpServletRespo
.oidcUserService(createOidcUserService())
.and()
.and()
.addFilterAfter(openIdReAuthorizeFilter, UsernamePasswordAuthenticationFilter.class);
.addFilterAfter(openIdReAuthorizeFilter, UsernamePasswordAuthenticationFilter.class);
}

private OAuth2AuthorizationRequestResolver authorizationRequestResolver() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import eu.openanalytics.containerproxy.util.ContextPathHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.ObjectPostProcessor;
Expand All @@ -40,6 +41,7 @@
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository;
import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter;
import org.springframework.security.saml2.provider.service.web.authentication.logout.Saml2LogoutRequestResolver;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
Expand All @@ -55,6 +57,7 @@
import static eu.openanalytics.containerproxy.auth.impl.saml.SAMLConfiguration.SAML_LOGOUT_SERVICE_LOCATION_PATH;
import static eu.openanalytics.containerproxy.auth.impl.saml.SAMLConfiguration.SAML_LOGOUT_SERVICE_RESPONSE_LOCATION_PATH;
import static eu.openanalytics.containerproxy.auth.impl.saml.SAMLConfiguration.SAML_SERVICE_LOCATION_PATH;
import static eu.openanalytics.containerproxy.ui.AuthController.AUTH_SUCCESS_URL;

@Component
@ConditionalOnProperty(name = "proxy.authentication", havingValue = "saml")
Expand All @@ -75,6 +78,10 @@ public class SAMLAuthenticationBackend implements IAuthenticationBackend {
@Inject
private Saml2LogoutRequestResolver saml2LogoutRequestResolver;

@Inject
@Lazy
private SavedRequestAwareAuthenticationSuccessHandler successHandler;

@Override
public String getName() {
return NAME;
Expand All @@ -98,7 +105,7 @@ public void configureHttpSecurity(HttpSecurity http, AuthorizedUrl anyRequestCon
.loginProcessingUrl(SAML_SERVICE_LOCATION_PATH)
.authenticationManager(new ProviderManager(samlAuthenticationProvider))
.failureHandler(failureHandler)
.defaultSuccessUrl("/", true))
.successHandler(successHandler))
.saml2Logout(saml -> saml
.logoutUrl(SAML_LOGOUT_SERVICE_LOCATION_PATH)
.logoutResponse(r -> r.logoutUrl(SAML_LOGOUT_SERVICE_RESPONSE_LOCATION_PATH))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
*/
package eu.openanalytics.containerproxy.auth.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer.AuthorizedUrl;
Expand All @@ -33,6 +35,15 @@
public class SocialAuthenticationBackend implements IAuthenticationBackend {

public static final String NAME = "social";

public SocialAuthenticationBackend() {
Logger logger = LoggerFactory.getLogger(getClass());
logger.warn("WARNING: ###");
logger.warn("WARNING: ###");
logger.warn("WARNING: Social authentication is deprecated and will be removed in the next version (3.1.0)!");
logger.warn("WARNING: ###");
logger.warn("WARNING: ###");
}

@Override
public String getName() {
Expand Down
Loading

0 comments on commit 2c71c88

Please sign in to comment.