diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml index 0bee47196707..d4b8d141b57a 100644 --- a/hapi-deployable-pom/pom.xml +++ b/hapi-deployable-pom/pom.xml @@ -60,7 +60,7 @@ true false false - false + true false true true diff --git a/hapi-fhir-opensrp-security-config/pom.xml b/hapi-fhir-opensrp-security-config/pom.xml new file mode 100644 index 000000000000..ed483b7bbe53 --- /dev/null +++ b/hapi-fhir-opensrp-security-config/pom.xml @@ -0,0 +1,115 @@ + + 4.0.0 + + + ca.uhn.hapi.fhir + hapi-deployable-pom + 5.4.0-PRE5-SNAPSHOT + ../../hapi-deployable-pom/pom.xml + + + hapi-fhir-opensrp-security-config + 0.0.1-PRE5-SNAPSHOT + + jar + + + + + org.springframework.boot + spring-boot-autoconfigure + ${spring_boot_version} + + + + javax.servlet + javax.servlet-api + true + + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework + spring-web + test + + + com.h2database + h2 + test + + + ch.qos.logback + logback-classic + test + + + org.slf4j + log4j-over-slf4j + test + 1.7.30 + + + org.keycloak + keycloak-spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework + spring-web + + + org.springframework.boot + spring-boot-starter-security + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring_boot_version} + pom + import + true + + + org.keycloak.bom + keycloak-adapter-bom + 13.0.0 + pom + import + + + + + + + + org.basepom.maven + duplicate-finder-maven-plugin + + true + + + + + + diff --git a/hapi-fhir-opensrp-security-config/src/main/java/autoconfigure/KeycloakSecurityConfig.java b/hapi-fhir-opensrp-security-config/src/main/java/autoconfigure/KeycloakSecurityConfig.java new file mode 100644 index 000000000000..ad96b76051cd --- /dev/null +++ b/hapi-fhir-opensrp-security-config/src/main/java/autoconfigure/KeycloakSecurityConfig.java @@ -0,0 +1,127 @@ +package autoconfigure; + +import org.keycloak.adapters.KeycloakConfigResolver; +import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; +import org.keycloak.adapters.springsecurity.KeycloakConfiguration; +import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; +import org.keycloak.adapters.springsecurity.client.KeycloakClientRequestFactory; +import org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate; +import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Scope; +import org.springframework.http.HttpMethod; +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.builders.WebSecurity; +import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; +import org.springframework.security.core.session.SessionRegistryImpl; +import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; +import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.Arrays; + +import static org.springframework.http.HttpMethod.DELETE; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.POST; +import static org.springframework.http.HttpMethod.PUT; + +@KeycloakConfiguration +public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { + + private static final String CORS_ALLOWED_HEADERS = "origin,content-type,accept,x-requested-with,Authorization"; + + private String opensrpAllowedSources=""; + + private long corsMaxAge=60; + + + private static final Logger logger = LoggerFactory.getLogger(KeycloakSecurityConfig.class); + + @Autowired + private KeycloakClientRequestFactory keycloakClientRequestFactory; + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) { + + SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper(); + grantedAuthorityMapper.setPrefix("ROLE_"); + + KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); + keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); + auth.authenticationProvider(keycloakAuthenticationProvider); + } + + @Bean + public KeycloakConfigResolver keycloakConfigResolver() { + return new KeycloakSpringBootConfigResolver(); + } + + @Bean + @Override + protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { + return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + super.configure(http); + logger.error("Inside configure method"); + http.cors() + .and() + .authorizeRequests() + .antMatchers("/").permitAll() + .antMatchers("/home").permitAll() + .mvcMatchers("/logout.do").permitAll() + .antMatchers("/fhir/**") + .authenticated() + .and() + .csrf() + .ignoringAntMatchers("/fhir/**") + .and() + .logout() + .logoutRequestMatcher(new AntPathRequestMatcher("logout.do", "GET")); + + } + + @Override + public void configure(WebSecurity web) throws Exception { + /* @formatter:off */ + web.ignoring().mvcMatchers("/js/**") + .and().ignoring().mvcMatchers("/css/**") + .and().ignoring().mvcMatchers("/images/**") + .and().ignoring().mvcMatchers("/html/**") + .and().ignoring().antMatchers(HttpMethod.OPTIONS, "/**") + .and().ignoring().antMatchers("/home") + .and().ignoring().antMatchers("/*") +// .and().ignoring().antMatchers("/fhir") + .and().ignoring().antMatchers("/fhir/metadata"); +// /* @formatter:on */ + } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(Arrays.asList(opensrpAllowedSources.split(","))); + configuration.setAllowedMethods(Arrays.asList(GET.name(), POST.name(), PUT.name(), DELETE.name())); + configuration.setAllowedHeaders(Arrays.asList(CORS_ALLOWED_HEADERS.split(","))); + configuration.setMaxAge(corsMaxAge); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } + + @Bean + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public KeycloakRestTemplate keycloakRestTemplate() { + return new KeycloakRestTemplate(keycloakClientRequestFactory); + } + +} diff --git a/hapi-fhir-opensrp-security-config/src/main/java/autoconfigure/SecurityAutoConfiguration.java b/hapi-fhir-opensrp-security-config/src/main/java/autoconfigure/SecurityAutoConfiguration.java new file mode 100644 index 000000000000..bddc6019a48a --- /dev/null +++ b/hapi-fhir-opensrp-security-config/src/main/java/autoconfigure/SecurityAutoConfiguration.java @@ -0,0 +1,41 @@ +package autoconfigure; + +/*- + * #%L + * hapi-fhir-spring-boot-autoconfigure + * %% + * Copyright (C) 2014 - 2021 Smile CDR, Inc. + * %% + * 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. + * #L% + */ + + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for HAPI FHIR. + * + * @author Reham Muzzamil + */ +@Configuration +@AutoConfigureAfter({KeycloakSecurityConfig.class}) +@EnableWebSecurity +@Import({ KeycloakSecurityConfig.class }) +public class SecurityAutoConfiguration { + +} diff --git a/hapi-fhir-opensrp-security-config/src/main/resources/META-INF/spring.factories b/hapi-fhir-opensrp-security-config/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000000..6cb366365697 --- /dev/null +++ b/hapi-fhir-opensrp-security-config/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=autoconfigure.SecurityAutoConfiguration diff --git a/hapi-fhir-opensrp-security-config/src/test/resources/logback-test.xml b/hapi-fhir-opensrp-security-config/src/test/resources/logback-test.xml new file mode 100644 index 000000000000..ee274734003e --- /dev/null +++ b/hapi-fhir-opensrp-security-config/src/test/resources/logback-test.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/src/main/resources/application.yml b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/src/main/resources/application.yml index 325409646b7b..188d7e9dbda4 100644 --- a/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/src/main/resources/application.yml +++ b/hapi-fhir-spring-boot/hapi-fhir-spring-boot-samples/hapi-fhir-spring-boot-sample-server-jersey/src/main/resources/application.yml @@ -18,4 +18,4 @@ management: enabled: false logging: level: - ca.uhn.fhir.jaxrs: debug \ No newline at end of file + ca.uhn.fhir.jaxrs: debug