비밀 값과 타입 안전 설정
설정 파일에 들어간 모든 값이 비밀은 아니지만, 비밀도 모두 외부 설정으로 들어옵니다. issuer URI와 허용 출처는 공개 가능한 운영 설정인 반면 DB 암호와 서명 키는 저장소, 이미지, 로그에 남아서는 안 됩니다. 둘을 같은 문자열처럼 다루지 않고 출처와 노출 정책을 나눕니다.
비밀 값은 설정이지만 평문 기본값은 아니다
개발 PC에서는 환경 변수가 간단하지만, 컨테이너에서는 파일로 마운트한 secret을 configtree:로 읽을 수 있습니다. 어느 출처를 쓰든 @ConfigurationProperties로 타입과 필수값을 검증하고, toString()·debug 로그·Actuator 환경 endpoint가 원문을 노출하지 않도록 해야 합니다.
비밀에 편리한 평문 기본값을 넣으면 설정 누락이 정상 시작으로 위장됩니다. 운영에서 반드시 주입해야 하는 값은 기본값 없이 두어 시작 시점에 실패하게 만듭니다.
검증된 ConfigurationProperties로 경계를 만든다
JWT issuer와 브라우저 출처, 감사 이벤트 무결성에 사용할 HMAC key를 한 설정 타입으로 묶습니다. record 전체를 로그로 출력하면 key까지 노출되므로 필요한 공개 필드만 따로 기록합니다.
package com.andongmin.studylog.security;
import java.net.URI;
import java.util.List;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@Validated
@ConfigurationProperties("study-log.security")
public record SecurityProperties(
@NotNull URI issuer,
@NotEmpty List<URI> allowedOrigins,
@NotBlank String auditHmacKey) {
}package com.andongmin.studylog.security;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SecurityProperties.class)
public class SecurityPropertiesConfiguration {
}study-log:
security:
issuer: https://id.example.test/realms/study-log
allowed-origins:
- https://study.example.com
audit-hmac-key: ${AUDIT_HMAC_KEY}
spring:
config:
import: optional:configtree:/run/secrets/Kubernetes나 Compose가 /run/secrets/study-log.security.audit-hmac-key 파일을 마운트하면 config tree가 같은 속성으로 읽습니다. 환경 변수와 config tree를 동시에 제공할 때는 어느 출처가 우선해야 하는지 배포 규칙을 하나로 정하고 혼용을 피합니다.
누락·오타·노출 로그를 시작 시점에 찾는다
필수값이 비었을 때 요청 처리 중이 아니라 시작 단계에서 실패하는지 확인합니다. 실패 로그에는 속성 이름과 검증 이유는 필요하지만 실제 key 값은 없어야 합니다.
AUDIT_HMAC_KEY= \
STUDY_LOG_SECURITY_ISSUER= \
./mvnw -q spring-boot:runissuer와 auditHmacKey가 비어 있으면 시작 단계에서 설정 검증이 실패해야 하며 로그에는 실제 비밀 값이 출력되지 않아야 합니다.비밀 주입 경계를 닫았으니 다음에는 TLS를 종료하는 프록시와 애플리케이션이 원래 요청 정보를 어떻게 신뢰할지 정합니다.