Skip to content

fix: EgovCassandraConfiguration이 자격증명 미설정 시 무인증 클러스터에 접속하지 못하는 문제 수정 - #325

Open
wantaekchoi wants to merge 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/cassandra-config-optional-credentials
Open

fix: EgovCassandraConfiguration이 자격증명 미설정 시 무인증 클러스터에 접속하지 못하는 문제 수정#325
wantaekchoi wants to merge 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/cassandra-config-optional-credentials

Conversation

@wantaekchoi

Copy link
Copy Markdown
Contributor

수정 사유 Reason for modification

  • 버그수정 Bug fixes
  • 기능개선 Enhancements
  • 기능추가 Adding features
  • 기타 Others

수정된 소스 내용 Modified source

EgovCassandraConfiguration.reactiveSession()withAuthCredentials(getUsername(), getPassword())를 무조건 호출합니다. username/password는 no-arg 생성자와 setter로만 채워지므로 설정하지 않으면 null인데, 드라이버는 이 값을 연결하기 전에 검증합니다.

SessionBuilder.withAuthCredentials
  -> new ProgrammaticPlainTextAuthProvider(username, password)
     -> Strings.requireNotEmpty(username, "username")
        null -> NullPointerException: username cannot be null
        ""   -> IllegalArgumentException: username cannot be empty

그래서 인증을 쓰지 않는 Cassandra(기본 배포의 AllowAllAuthenticator)에는 접속 자체가 되지 않습니다.

형제 EgovRedisConfiguration.reactiveRedisConnectionFactory()는 같은 상황을 이미 다르게 처리합니다.

if (password != null && !password.trim().isEmpty()) {
    redisStandaloneConfiguration.setPassword(password);
}

이 가드는 v5.0.0 FINAL(4d97ab5)에서 새로 들어왔고(v4.3.0은 무조건 setPassword 호출), 같은 릴리스에서 Cassandra 쪽 diff는 저작권 표기와 @author뿐입니다.

AS-IS

return new DefaultBridgedReactiveSession(CqlSession.builder()
        .withLocalDatacenter(getDataCenterName())
        .withKeyspace(getKeyspaceName())
        .addContactPoint(InetSocketAddress.createUnresolved(getContactPoint(), getPort()))
        .withAuthCredentials(getUsername(), getPassword())
        .build());

TO-BE

CqlSessionBuilder builder = CqlSession.builder()
        .withLocalDatacenter(getDataCenterName())
        .withKeyspace(getKeyspaceName())
        .addContactPoint(InetSocketAddress.createUnresolved(getContactPoint(), getPort()));
// 자격증명을 설정하지 않으면 인증 없이 접속한다. 형제 EgovRedisConfiguration도 같은 처리다.
// 비어 있다는 판정은 드라이버의 Strings.requireNotEmpty와 같은 기준(null 또는 길이 0)을 쓴다.
// 한쪽만 설정된 경우는 설정 실수이므로 드라이버가 그대로 검증하도록 넘긴다.
boolean hasUsername = getUsername() != null && !getUsername().isEmpty();
boolean hasPassword = getPassword() != null && !getPassword().isEmpty();
if (hasUsername || hasPassword) {
    builder = builder.withAuthCredentials(getUsername(), getPassword());
}
return new DefaultBridgedReactiveSession(builder.build());

영향 범위

username/password가 양쪽 다 null이거나 빈 문자열일 때만 동작이 달라집니다. 종전에는 예외로 막혔고 이제 인증 없이 접속합니다. 한쪽만 설정된 경우는 종전대로 드라이버 검증에 맡깁니다.

비어 있다는 판정에 trim()을 쓰지 않은 것은 드라이버의 Strings.requireNotEmpty가 길이 0만 보기 때문입니다. 기준을 맞춰야 "건너뛸지 판단한 값"과 "실제로 넘기는 값"이 어긋나지 않습니다.

JUnit 테스트 JUnit tests

  • JUnit 테스트 JUnit tests
  • 수동 테스트 Manual testing

EgovCassandraConfigurationTest 4건을 추가했습니다. 기존 테스트 설정(CassandraConfiguration)이 username/password를 항상 채워 이 경로를 밟지 않습니다.

수정 지점만 되돌린 상태(RED)

[ERROR] Tests run: 4, Failures: 2, Errors: 0, Skipped: 0
[ERROR]   EgovCassandraConfigurationTest.reactiveSessionWithoutCredentials 자격증명 검증이 연결 시도를 막았다: java.lang.NullPointerException: username cannot be null
[ERROR]   EgovCassandraConfigurationTest.reactiveSessionWithBlankCredentials 자격증명 검증이 연결 시도를 막았다: java.lang.IllegalArgumentException: username cannot be empty

수정 후(GREEN)

[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

이 모듈은 pom.xml<skipTests>true</skipTests>가 있어 로컬 확인 시에만 false로 바꿨다가 되돌렸습니다(#315·#316과 같은 방식). 인증 없는 Cassandra 4.1 컨테이너를 띄우고 mvn clean test로 모듈 전체를 돌리면 기존 CassandraTest(CRUD)까지 포함해 통과합니다.

[INFO] Running org.egovframe.rte.psl.reactive.cassandra.repository.CassandraTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] Running org.egovframe.rte.psl.reactive.cassandra.connect.EgovCassandraConfigurationTest
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0

서버가 있든 없든 같은 결과가 나옵니다. 테스트가 연결 성공이 아니라 자격증명 검증에만 반응하기 때문입니다.

reactiveSession()이 withAuthCredentials(getUsername(), getPassword())를 무조건
호출한다. username/password는 no-arg 생성자와 setter로만 채워지므로 설정하지
않으면 null인데, 드라이버는 이 값을 연결 전에 검증한다 —
ProgrammaticPlainTextAuthProvider가 Strings.requireNotEmpty로 null이면
NullPointerException, 빈 문자열이면 IllegalArgumentException을 던진다.
그래서 인증이 없는 Cassandra(기본 배포의 AllowAllAuthenticator)에는 접속 자체가
불가능하다.

형제 EgovRedisConfiguration은 같은 상황을 이미 다르게 처리한다.
reactiveRedisConnectionFactory()는 password가 비어 있으면 setPassword를
건너뛴다. 이 가드는 v5.0.0 FINAL에서 새로 들어왔고(v4.3.0은 무조건 setPassword
호출), 같은 릴리스에서 Cassandra 쪽은 저작권 표기와 @author만 바뀌었다.

자격증명이 양쪽 다 비어 있으면 withAuthCredentials를 건너뛴다. 비어 있다는
판정은 드라이버의 Strings.requireNotEmpty와 같은 기준(null 또는 길이 0)을 써서
판정 기준과 실제로 넘기는 값이 어긋나지 않게 했다. 한쪽만 설정된 경우는 설정
실수이므로 종전대로 드라이버 검증에 맡긴다.

기존 테스트 설정(CassandraConfiguration)이 username/password를 항상 채워
이 경로를 밟지 않으므로 자격증명 처리 테스트 4건을 추가했다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant