Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -1219,13 +1219,13 @@
"targets": [
{
"datasource": { "type": "prometheus", "uid": "DS_PROMETHEUS" },
"expr": "sum(rate(kafka_consumer_fetch_manager_records_consumed_total{job=\"catchtable-app\"}[1m])) by (topic)",
"expr": "sum(rate(kafka_consumer_fetch_manager_records_consumed_total{job=\"catchtable-app\", topic!~\".*_.*\"}[1m])) by (topic)",
"legendFormat": "소비 - {{topic}}",
"refId": "A"
},
{
"datasource": { "type": "prometheus", "uid": "DS_PROMETHEUS" },
"expr": "sum(rate(kafka_producer_record_send_total{job=\"catchtable-app\"}[1m])) by (topic)",
"expr": "sum(rate(kafka_producer_record_send_total{job=\"catchtable-app\", topic!~\".*_.*\"}[1m])) by (topic)",
"legendFormat": "생산 - {{topic}}",
"refId": "B"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2192,7 +2192,7 @@
"type": "timeseries",
"targets": [
{
"expr": "sum by (topic) (rate(kafka_consumer_fetch_manager_records_consumed_total[1m]))",
"expr": "sum by (topic) (rate(kafka_consumer_fetch_manager_records_consumed_total{topic!~\".*_.*\"}[1m]))",
"legendFormat": "{{topic}}",
"refId": "A",
"datasource": { "type": "prometheus", "uid": "DS_PROMETHEUS" }
Expand Down
27 changes: 26 additions & 1 deletion src/main/java/com/catchtable/global/config/CacheConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.catchtable.global.config;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -19,9 +23,12 @@ public class CacheConfig {

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
GenericJackson2JsonRedisSerializer valueSerializer =
new GenericJackson2JsonRedisSerializer(buildCacheObjectMapper());

RedisCacheConfiguration defaults = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer))
.disableCachingNullValues();

Map<String, RedisCacheConfiguration> cacheConfigs = Map.of(
Expand All @@ -33,4 +40,22 @@ public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory)
.withInitialCacheConfigurations(cacheConfigs)
.build();
}

// record 클래스는 final 이라 GenericJackson2JsonRedisSerializer 의 기본 NON_FINAL typing 에서는
// @class 메타 필드가 안 붙어서 역직렬화 시 "expected VALUE_STRING for type id" 실패.
// EVERYTHING typing 으로 record/List 모두 type info 포함되도록 명시.
// BasicPolymorphicTypeValidator 로 Object 하위 타입만 허용해 deserialization gadget 위험 차단.
private ObjectMapper buildCacheObjectMapper() {
BasicPolymorphicTypeValidator validator = BasicPolymorphicTypeValidator.builder()
.allowIfBaseType(Object.class)
.build();
Comment on lines +49 to +51

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

BasicPolymorphicTypeValidator를 설정할 때 allowIfBaseType(Object.class)를 사용하는 것은 Java의 모든 객체(Object를 상속받는 모든 클래스)의 역직렬화를 허용하게 됩니다.\n\n주석에는 "Object 하위 타입만 허용해 deserialization gadget 위험 차단"이라고 작성되어 있으나, 실제로는 거의 모든 클래스가 Object를 상속받기 때문에 **알려진 모든 Deserialization Gadget(예: 원격 코드 실행을 유발하는 취약한 클래스들)의 역직렬화가 허용되어 심각한 보안 취약점(RCE)**이 발생할 수 있습니다.\n\n따라서 Object.class 전체를 허용하는 대신, 캐싱 대상이 되는 안전한 패키지 경로(예: com.catchtable)나 특정 클래스들만 허용하도록 제한해야 합니다.

        BasicPolymorphicTypeValidator validator = BasicPolymorphicTypeValidator.builder()\n                .allowIfSubType("com.catchtable")\n                .allowIfSubType(java.util.Collection.class)\n                .allowIfSubType(java.util.Map.class)\n                .build();


return new ObjectMapper()
.registerModule(new JavaTimeModule())
.activateDefaultTyping(
validator,
ObjectMapper.DefaultTyping.EVERYTHING,
JsonTypeInfo.As.PROPERTY
);
}
}
Loading