Spring Security Config hasRole not working 해결

정명진·2023년 5월 2일
0
post-custom-banner

프로메테우스에 role 이 ADMIN 인 경우만 작동할 수 있게 하려고 설정을 했다.

# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "sample"
    metrics_path: '/actuator/prometheus'
    scrape_interval: 1s
    static_configs:
      - targets: ['localhost:8080']
    bearer_token: token

다음은 Security Config 이다

 @Bean
    protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .accessDeniedHandler(jwtAccessDeniedHandler)
                .and()
                .headers()
                .frameOptions()
                .sameOrigin()
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/actuator/**")
                .hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .apply(new JwtConfig(tokenProvider, redisTemplate));
        return http.build();
    }

그리고 당연히 정상적으로 작동할 것이라 생각했는데 서버에서 403을 return 한다고 문구가 떴다.

뭐가 문제인가보니... 커스텀으로 지정했던 UserRole이 문제였다.

hasRole에 실제로 내가 값을 쓰면 prefix가 생략되어 있는 형태였다!

즉 hasRole("ADMIN")을 썼지만 실제로는 유저의 role이 prefix+"ADMIN"이여야 정상적으로 인식이 되는 문제였다.

실제로 hasRole 옵션을 따라가보니

public ExpressionUrlAuthorizationConfigurer(ApplicationContext context) {
		String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
		if (grantedAuthorityDefaultsBeanNames.length == 1) {
			GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(grantedAuthorityDefaultsBeanNames[0],
					GrantedAuthorityDefaults.class);
			this.rolePrefix = grantedAuthorityDefaults.getRolePrefix();
		}
		else {
			this.rolePrefix = "ROLE_";
		}
		this.REGISTRY = new ExpressionInterceptUrlRegistry(context);
	}
    
private static String hasRole(String rolePrefix, String role) {
		Assert.notNull(role, "role cannot be null");
		Assert.isTrue(rolePrefix.isEmpty() || !role.startsWith(rolePrefix), () -> "role should not start with '"
				+ rolePrefix + "' since it is automatically inserted. Got '" + role + "'");
		return "hasRole('" + rolePrefix + role + "')";
	}    

이렇게 되어있다. 즉 prefix까지 붙은 형태로 enum 에서 정의해야 정상적으로 인식을 하는것이다.

그래서 UserRole enum을 다음과 같이 변경하였고

public enum UserRole {
    ROLE_NORMAL, ROLE_ADMIN
}

그후 다시 토큰을 발급받아 프로메테우스를 실행하니 정상적으로 연결할 수 있었다.

사실 이 방법 말고도 aws에서 특정 포트를 프로메테우스 서버에서만 연결을 허용해준다던가 해서 해결을 할 수 있지만 꼭 해결하고 싶어서 도전을 하게 되었다..

profile
개발자로 입사했지만 정체성을 잃어가는중... 다시 준비 시작이다..
post-custom-banner

0개의 댓글