Skip to content

Commit

Permalink
feat: ✨ 애플리케이션 헬스 체크를 위한 Actuator 의존성 추가 (#146)
Browse files Browse the repository at this point in the history
* chore: api 모듈 actuator 의존성 추가

* fix: security filter actuator public endpoint 옵션 설정
  • Loading branch information
psychology50 authored Aug 7, 2024
1 parent 84dab2b commit 03994d7
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 56 deletions.
3 changes: 3 additions & 0 deletions pennyway-app-external-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web:3.2.3'
implementation 'org.springframework.boot:spring-boot-starter-validation:3.2.3'

/* Actuator */
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.3.2'

/* testcontainer */
testImplementation "org.junit.jupiter:junit-jupiter:5.8.1"
testImplementation "org.testcontainers:testcontainers:1.19.7"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package kr.co.pennyway.api.config.security;

import static kr.co.pennyway.api.config.security.WebSecurityUrls.*;

import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.security.ConditionalOnDefaultWebSecurity;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
Expand All @@ -22,69 +21,69 @@
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.web.cors.CorsConfigurationSource;

import lombok.RequiredArgsConstructor;
import static kr.co.pennyway.api.config.security.WebSecurityUrls.AUTHENTICATED_ENDPOINTS;

@Configuration
@EnableWebSecurity
@ConditionalOnDefaultWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private static final String[] READ_ONLY_PUBLIC_ENDPOINTS = {"/favicon.ico", "/v1/duplicate/**"};
private static final String[] PUBLIC_ENDPOINTS = {"/v1/questions/**"};
private static final String[] ANONYMOUS_ENDPOINTS = {"/v1/auth/**", "/v1/phone/**", "/v1/find/**"};
private static final String[] SWAGGER_ENDPOINTS = {"/api-docs/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger",};
private static final String[] READ_ONLY_PUBLIC_ENDPOINTS = {"/favicon.ico", "/v1/duplicate/**", "/actuator/health"};
private static final String[] PUBLIC_ENDPOINTS = {"/v1/questions/**"};
private static final String[] ANONYMOUS_ENDPOINTS = {"/v1/auth/**", "/v1/phone/**", "/v1/find/**"};
private static final String[] SWAGGER_ENDPOINTS = {"/api-docs/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger",};

private final SecurityAdapterConfig securityAdapterConfig;
private final CorsConfigurationSource corsConfigurationSource;
private final AccessDeniedHandler accessDeniedHandler;
private final AuthenticationEntryPoint authenticationEntryPoint;
private final SecurityAdapterConfig securityAdapterConfig;
private final CorsConfigurationSource corsConfigurationSource;
private final AccessDeniedHandler accessDeniedHandler;
private final AuthenticationEntryPoint authenticationEntryPoint;

@Bean
@Profile({"local", "dev", "test"})
@Order(SecurityProperties.BASIC_AUTH_ORDER)
public SecurityFilterChain filterChainDev(HttpSecurity http) throws Exception {
return defaultSecurity(http)
.cors((cors) -> cors.configurationSource(corsConfigurationSource))
.authorizeHttpRequests(
auth -> defaultAuthorizeHttpRequests(auth)
.requestMatchers(SWAGGER_ENDPOINTS).permitAll()
.anyRequest().authenticated()
).build();
}
@Bean
@Profile({"local", "dev", "test"})
@Order(SecurityProperties.BASIC_AUTH_ORDER)
public SecurityFilterChain filterChainDev(HttpSecurity http) throws Exception {
return defaultSecurity(http)
.cors((cors) -> cors.configurationSource(corsConfigurationSource))
.authorizeHttpRequests(
auth -> defaultAuthorizeHttpRequests(auth)
.requestMatchers(SWAGGER_ENDPOINTS).permitAll()
.anyRequest().authenticated()
).build();
}

@Bean
@Profile({"prod"})
@Order(SecurityProperties.BASIC_AUTH_ORDER)
public SecurityFilterChain filterChainProd(HttpSecurity http) throws Exception {
return defaultSecurity(http)
.cors(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(
auth -> defaultAuthorizeHttpRequests(auth).anyRequest().authenticated()
).build();
}
@Bean
@Profile({"prod"})
@Order(SecurityProperties.BASIC_AUTH_ORDER)
public SecurityFilterChain filterChainProd(HttpSecurity http) throws Exception {
return defaultSecurity(http)
.cors(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(
auth -> defaultAuthorizeHttpRequests(auth).anyRequest().authenticated()
).build();
}

private HttpSecurity defaultSecurity(HttpSecurity http) throws Exception {
return http.httpBasic(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.formLogin(AbstractHttpConfigurer::disable)
.logout(AbstractHttpConfigurer::disable)
.with(securityAdapterConfig, Customizer.withDefaults())
.exceptionHandling(
exception -> exception
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint)
);
}
private HttpSecurity defaultSecurity(HttpSecurity http) throws Exception {
return http.httpBasic(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.formLogin(AbstractHttpConfigurer::disable)
.logout(AbstractHttpConfigurer::disable)
.with(securityAdapterConfig, Customizer.withDefaults())
.exceptionHandling(
exception -> exception
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint)
);
}

private AbstractRequestMatcherRegistry<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizedUrl> defaultAuthorizeHttpRequests(
AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry auth) {
return auth.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.requestMatchers(HttpMethod.OPTIONS, "*").permitAll()
.requestMatchers(HttpMethod.GET, READ_ONLY_PUBLIC_ENDPOINTS).permitAll()
.requestMatchers(PUBLIC_ENDPOINTS).permitAll()
.requestMatchers(AUTHENTICATED_ENDPOINTS).authenticated() // FIXME: 2024-04-23 /v1/auth가 anonymous로 설정되어 있어서 authenticated로 덮어씀.
.requestMatchers(ANONYMOUS_ENDPOINTS).anonymous();
}
private AbstractRequestMatcherRegistry<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizedUrl> defaultAuthorizeHttpRequests(
AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry auth) {
return auth.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.requestMatchers(HttpMethod.OPTIONS, "*").permitAll()
.requestMatchers(HttpMethod.GET, READ_ONLY_PUBLIC_ENDPOINTS).permitAll()
.requestMatchers(PUBLIC_ENDPOINTS).permitAll()
.requestMatchers(AUTHENTICATED_ENDPOINTS).authenticated() // FIXME: 2024-04-23 /v1/auth가 anonymous로 설정되어 있어서 authenticated로 덮어씀.
.requestMatchers(ANONYMOUS_ENDPOINTS).anonymous();
}
}

0 comments on commit 03994d7

Please sign in to comment.