Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LMSA-8950 - q3 library updates and spring boot upgrade #10

Merged
merged 2 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
cache: maven

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/kube-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
name: Maven Build
runs-on: self-hosted
container:
image: maven:3.9.4-eclipse-temurin-17
image: maven:3.9.9-eclipse-temurin-21
environment: ${{ github.event.inputs.server_env }}
steps:
- name: Clone GitHub root repository
Expand All @@ -74,15 +74,15 @@ jobs:
- name: Create maven settings.xml
run: echo -n '${{ secrets.LMS_MAVEN_SETTINGS }}' | base64 -d > /root/.m2/settings.xml
- name: Maven Build
run: mvn clean install -P '${{ vars.BUILD_PROFILES}}'
run: mvn clean install -B -P '${{ vars.BUILD_PROFILES}}'
working-directory: tools/${{ vars.DEPLOY_DIR }}
- name: copy jar file
run: |
mkdir -p deployments/${{ vars.DEPLOY_DIR }}/lib
cp tools/${{ vars.DEPLOY_DIR }}/target/${{ vars.JAR_FILE }} deployments/${{ vars.DEPLOY_DIR }}/lib/${{ vars.JAR_FILE }}
- name: build/push docker image
run: |
mvn clean install -P docker-push -D dockerfile.username=${{ secrets.LMS_REGISTRY_USERNAME }} \
mvn clean install -B -P docker-push -D dockerfile.username=${{ secrets.LMS_REGISTRY_USERNAME }} \
-D dockerfile.password=${{ secrets.LMS_REGISTRY_PASSWORD }} -D docker_repository_base=registry.docker.iu.edu/lms/ \
-D docker_tag=${{ vars.DOCKER_TAG }}
working-directory: deployments/${{ vars.DEPLOY_DIR }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:

steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Build with Maven
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
cache: maven
- name: Release prepare/perform
Expand Down
48 changes: 26 additions & 22 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.14</version>
<version>3.2.9</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>

<version>5.0.5-SNAPSHOT</version>
<version>6.0.0-SNAPSHOT</version>
<description>LTI tool which exports sis grades</description>
<url>https://github.com/indiana-university/lms-canvas-sis-grades-export</url>
<inceptionYear>2015</inceptionYear>
Expand Down Expand Up @@ -59,20 +59,20 @@
<denodo-hibernate-dialect.version>8.0.20201021</denodo-hibernate-dialect.version>
<denodo-jdbc.version>8.0.2</denodo-jdbc.version>
<frontend-maven-plugin.version>1.11.0</frontend-maven-plugin.version>
<git-commit-id-maven-plugin.version>5.0.0</git-commit-id-maven-plugin.version>
<hibernate5-ddl-maven-plugin.version>2.5.0</hibernate5-ddl-maven-plugin.version>
<java.version>17</java.version>
<jdk.source>17</jdk.source>
<jdk.target>17</jdk.target>
<lms-embedded-services.version>5.2.14</lms-embedded-services.version>
<lms-team-spring-boot-it12>4.8</lms-team-spring-boot-it12>
<opencsv.version>5.8</opencsv.version>
<spring-cloud-starter-parent.version>2021.0.8</spring-cloud-starter-parent.version>
<springdoc-openapi-ui.version>1.7.0</springdoc-openapi-ui.version>
<git-commit-id-maven-plugin.version>9.0.1</git-commit-id-maven-plugin.version>
<hibernate6-ddl-maven-plugin.version>1.0.2</hibernate6-ddl-maven-plugin.version>
<java.version>21</java.version>
<jdk.source>21</jdk.source>
<jdk.target>21</jdk.target>
<lms-embedded-services.version>6.0.2</lms-embedded-services.version>
<lms-team-spring-boot-it12>6.5.0</lms-team-spring-boot-it12>
<opencsv.version>5.9</opencsv.version>
<spring-cloud-starter-parent.version>2023.0.3</spring-cloud-starter-parent.version>
<springdoc-openapi-ui.version>2.6.0</springdoc-openapi-ui.version>

<plugins.compiler.version>3.11.0</plugins.compiler.version>
<plugins.license.version>2.0.0</plugins.license.version>
<plugins.release.version>3.0.0</plugins.release.version>
<plugins.compiler.version>3.13.0</plugins.compiler.version>
<plugins.license.version>2.4.0</plugins.license.version>
<plugins.release.version>3.1.1</plugins.release.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -118,9 +118,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>edu.iu.uits.lms</groupId>
<artifactId>lms-canvas-redis-config</artifactId>
<version>${lms-embedded-services.version}</version>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>edu.iu.uits.lms</groupId>
Expand Down Expand Up @@ -175,14 +174,19 @@
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc-openapi-ui.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-properties-migrator</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -226,8 +230,8 @@
</plugin>
<plugin>
<groupId>de.jpdigital</groupId>
<artifactId>hibernate54-ddl-maven-plugin</artifactId>
<version>${hibernate5-ddl-maven-plugin.version}</version>
<artifactId>hibernate65-ddl-maven-plugin</artifactId>
<version>${hibernate6-ddl-maven-plugin.version}</version>
<executions>
<execution>
<goals>
Expand All @@ -239,7 +243,7 @@
<configuration>
<dialects>
<param>h2</param>
<param>postgresql9</param>
<param>postgresql</param>
</dialects>
<packages>
<param>edu.iu.uits.lms.iuonly</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import edu.iu.uits.lms.iuonly.config.EnableIuOnlyClient;
import edu.iu.uits.lms.lti.config.EnableGlobalErrorHandler;
import edu.iu.uits.lms.lti.config.EnableLtiClient;
import edu.iu.uits.lms.redis.config.EnableRedisConfiguration;
import edu.iu.uits.lms.sisgradesexport.config.ToolConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -56,7 +55,6 @@
@SpringBootApplication
@EnableGlobalErrorHandler
@Slf4j
@EnableRedisConfiguration
@EnableCookieFilter(ignoredRequestPatterns = {"/rest/**"})
@EnableLtiClient(toolKeys = "lms_sis_grade_export")
@EnableCanvasClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
@EnableWebMvc
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@EnableMethodSecurity(securedEnabled = true, prePostEnabled = true)
@Slf4j
public class ApplicationConfig implements WebMvcConfigurer {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* #L%
*/

import jakarta.persistence.EntityManagerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
Expand All @@ -46,7 +47,6 @@
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,118 +38,92 @@
import edu.iu.uits.lms.common.oauth.CustomJwtAuthenticationConverter;
import edu.iu.uits.lms.lti.service.LmsDefaultGrantedAuthoritiesMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionAuthorizationManager;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
import uk.ac.ox.ctl.lti13.Lti13Configurer;

import static edu.iu.uits.lms.lti.LTIConstants.BASE_USER_ROLE;
import static edu.iu.uits.lms.lti.LTIConstants.BASE_USER_AUTHORITY;
import static edu.iu.uits.lms.lti.LTIConstants.WELL_KNOWN_ALL;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 5)
public static class RestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

@Override
public void configure(HttpSecurity http) throws Exception {
http.cors().and()
.requestMatchers().antMatchers("/rest/**", "/api/**")
.and()
.authorizeRequests()
.antMatchers("/rest/sis/grades/**")
.access("hasAuthority('SCOPE_lms:sis:grades') or (hasAuthority('SCOPE_lms:rest') and hasAuthority('ROLE_LMS_REST_ADMINS'))")
.antMatchers("/rest/**")
.access("hasAuthority('SCOPE_lms:rest') and hasAuthority('ROLE_LMS_REST_ADMINS')")
.antMatchers("/api/**").permitAll()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.oauth2ResourceServer()
.jwt().jwtAuthenticationConverter(new CustomJwtAuthenticationConverter());

http.apply(new RestSecurityLoggingConfig());
}
@Autowired
private LmsDefaultGrantedAuthoritiesMapper lmsDefaultGrantedAuthoritiesMapper;

@Bean
@Order(5)
public SecurityFilterChain restFilterChain(HttpSecurity http) throws Exception {

http.cors(Customizer.withDefaults())
.securityMatcher("/rest/**", "/api/**")
.authorizeHttpRequests(authz -> authz
.requestMatchers("/rest/sis/grades/**")
.access(new WebExpressionAuthorizationManager("hasAuthority('SCOPE_lms:sis:grades') or (hasAuthority('SCOPE_lms:rest') and hasAuthority('ROLE_LMS_REST_ADMINS'))"))
.requestMatchers("/rest/**")
.access(new WebExpressionAuthorizationManager("hasAuthority('SCOPE_lms:rest') and hasAuthority('ROLE_LMS_REST_ADMINS')"))
.requestMatchers("/api/**").permitAll()
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2ResourceServer(oauth -> oauth
.jwt(jwt -> jwt.jwtAuthenticationConverter(new CustomJwtAuthenticationConverter())))
.with(new RestSecurityLoggingConfig(), log -> {});
return http.build();
}

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 4)
public static class AppWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

@Autowired
private LmsDefaultGrantedAuthoritiesMapper lmsDefaultGrantedAuthoritiesMapper;

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers(WELL_KNOWN_ALL, "/error", "/app/**")
.and()
.authorizeRequests()
.antMatchers(WELL_KNOWN_ALL, "/error").permitAll()
.antMatchers("/**").hasRole(BASE_USER_ROLE)
.withObjectPostProcessor(new LmsFilterSecurityInterceptorObjectPostProcessor())
.and()
.headers()
.contentSecurityPolicy("style-src 'self'; form-action 'self'; frame-ancestors 'self' https://*.instructure.com")
.and()
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN));

//Setup the LTI handshake
Lti13Configurer lti13Configurer = new Lti13Configurer()
.grantedAuthoritiesMapper(lmsDefaultGrantedAuthoritiesMapper);

http.apply(lti13Configurer);

//Fallback for everything else
http.requestMatchers().antMatchers("/**")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.withObjectPostProcessor(new LmsFilterSecurityInterceptorObjectPostProcessor())
.and()
.headers()
.contentSecurityPolicy("style-src 'self'; form-action 'self'; frame-ancestors 'self' https://*.instructure.com")
.and()
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN));
}

@Override
public void configure(WebSecurity web) throws Exception {
// ignore everything except paths specified
web.ignoring().antMatchers("/app/css/**", "/app/js/**", "/favicon.ico");
}

@Bean
@Order(6)
public SecurityFilterChain appFilterChain(HttpSecurity http) throws Exception {
http.securityMatcher(WELL_KNOWN_ALL, "/error", "/app/**")
.authorizeHttpRequests(authz -> authz
.requestMatchers(WELL_KNOWN_ALL, "/error").permitAll()
.requestMatchers("/**").hasAuthority(BASE_USER_AUTHORITY)
.withObjectPostProcessor(new LmsFilterSecurityInterceptorObjectPostProcessor())
)
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp.policyDirectives("style-src 'self' 'unsafe-inline'; form-action 'self'; frame-ancestors 'self' https://*.instructure.com"))
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN))
);
return http.build();
}

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER - 2)
public static class CatchAllSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
// ignore everything except paths specified
return web -> web.ignoring().requestMatchers("/app/css/**", "/app/js/**", "/favicon.ico");
}

@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/**")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.withObjectPostProcessor(new LmsFilterSecurityInterceptorObjectPostProcessor())
.and()
.headers()
.contentSecurityPolicy("style-src 'self'; form-action 'self'; frame-ancestors 'self' https://*.instructure.com")
.and()
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN));
}
@Bean
@Order(7)
public SecurityFilterChain catchallFilterChain(HttpSecurity http) throws Exception {
//Setup the LTI handshake
http.with(new Lti13Configurer(), lti ->
lti.setSecurityContextRepository(new HttpSessionSecurityContextRepository())
.grantedAuthoritiesMapper(lmsDefaultGrantedAuthoritiesMapper));

http.securityMatcher("/**")
.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()
.withObjectPostProcessor(new LmsFilterSecurityInterceptorObjectPostProcessor()))
.headers(headers -> headers
.contentSecurityPolicy(csp ->
csp.policyDirectives("style-src 'self' 'unsafe-inline'; form-action 'self'; frame-ancestors 'self' https://*.instructure.com"))
.referrerPolicy(referrer -> referrer
.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN))
);

return http.build();
}
}
Loading