5db83e485d
- Jenkinsfile 도입: 자동 빌드/테스트 워크플로 작성 - bypass 모드 도입: 시스템 프로퍼티로 암복호화 설정 분기
279 lines
12 KiB
Markdown
279 lines
12 KiB
Markdown
# damo-manager
|
|
|
|
Penta scpdb 라이브러리 래퍼. **단일 jar (`damo-manager.jar`)** 로 운영/로컬 양쪽 환경에서 동작한다.
|
|
|
|
## 동작 모드
|
|
|
|
클래스 로딩 시점에 시스템 프로퍼티로 한 번만 결정된다. **기본은 bypass(무변환)** 이며, 실제 암복호화는 명시적으로 켜야 한다.
|
|
|
|
| 옵션 | 결정되는 모드 | encrypt/decrypt | hash |
|
|
|---|---|---|---|
|
|
| (없음, 기본) | **bypass** | **원문 그대로 (무변환)** | **원문 그대로 (무변환)** |
|
|
| `-Ddamo-manager.enabled=true` + scpdb 존재 | **real** | `ScpEncB64`/`ScpDecB64` | `ScpHashB64` |
|
|
| `-Ddamo-manager.enabled=true` + scpdb 부재 | **fake** | Base64 round-trip | JRE `MessageDigest` |
|
|
| `-Ddamo-manager.require-real=true` | **real** (강제) | `ScpEncB64`/`ScpDecB64` | `ScpHashB64` |
|
|
|
|
- **bypass (기본값)**: 암복호화/해시를 **전혀 수행하지 않고 입력을 그대로 반환**. fake 와 달리 Base64 인코딩조차 하지 않는 완전 무변환. 시작 시 경고 배너 출력. 평문 그대로 저장/조회하거나 암복호화 계층을 통째로 끌 때 사용
|
|
- **real (`-Ddamo-manager.enabled=true` + scpdb)**: 실제 `ScpEncB64`/`ScpDecB64`/`ScpHashB64` 호출
|
|
- **fake (`-Ddamo-manager.enabled=true`, scpdb 없음)**: scpdb 부재 시 자동 진입. 시작 시 경고 배너. 암복호화는 단순 Base64, 해시는 JRE `MessageDigest`
|
|
- **require-real (`-Ddamo-manager.require-real=true`)**: **운영 보호 플래그.** real 모드로만 동작해야 하며, scpdb 가 없어 fake/bypass 로 떨어질 상황이면 **조용히 폴백하지 않고 클래스 로딩 시점에 즉시 실패**(`IllegalStateException` → `ExceptionInInitializerError`)한다. `enabled` 를 함의하므로 운영 서버에서는 이 플래그 하나만 켜면 "real 아니면 기동 거부"가 된다
|
|
|
|
> bypass / fake 모두 **운영 절대 금지**. 운영 서버에는 **`-Ddamo-manager.require-real=true`** 를 주어 fake/bypass 동작을 원천 차단할 것.
|
|
|
|
## 빌드
|
|
|
|
```bash
|
|
cd damo-manager
|
|
gradle clean build # wrapper 미사용. gradle 단독 실행
|
|
ls build/libs/ # damo-manager.jar
|
|
```
|
|
|
|
JDK 8 toolchain 을 요구한다 (`build.gradle` 의 `JavaLanguageVersion.of(8)`). `JAVA_HOME` 이 JDK 8 이거나 Gradle 이 시스템에서 JDK 8 을 auto-detect 할 수 있어야 한다.
|
|
|
|
산출 jar 는 라이브러리이자 **실행 가능한 CLI** 다 (manifest `Main-Class: com.eactive.ext.djb.DamoCli`). CLI 사용법은 아래 [CLI](#cli-java--jar) 참고.
|
|
|
|
스모크 검증:
|
|
|
|
```bash
|
|
gradle runBypassSmoke # bypass 모드 (기본값, 옵션 없음)
|
|
gradle runFakeSmoke # fake 모드 (-Ddamo-manager.enabled=true, scpdb 부재)
|
|
```
|
|
|
|
### Jenkins 빌드
|
|
|
|
저장소 루트에 `Jenkinsfile` 이 있다. `djb-vm` 에이전트에서 `pollSCM` 으로 트리거되며 다음을 수행한다.
|
|
|
|
1. **Build JAR** — `gradle clean build --no-daemon`
|
|
2. **Smoke test** — fake / bypass 모드 main + CLI `info` 실행
|
|
3. **Package & checksum** — `build/dist/` 에 `damo-manager.jar` + `README.md` 복사 후 `SHA1SUMS` / `SHA256SUMS` 생성
|
|
4. **archiveArtifacts** — `damo-manager.jar`, `README.md`, `SHA1SUMS`, `SHA256SUMS` 보관 (fingerprint)
|
|
|
|
빌드 환경(JDK8/Gradle 경로)은 다른 djb-eapim Jenkinsfile 과 동일한 `/apps/opts/*` 경로를 사용한다.
|
|
|
|
## CLI (java -jar)
|
|
|
|
`damo-manager.jar` 를 `java -jar` 로 직접 실행하면 encrypt/decrypt/hash 를 즉석에서 테스트할 수 있다. **대화식(REPL)** 과 **파라미터식** 둘 다 지원하며, 파라미터식은 text 인자를 생략하면 **stdin → stdout** 파이프로 동작한다.
|
|
|
|
```bash
|
|
# 대화식(REPL): 명령을 줄 단위로 입력
|
|
java -jar damo-manager.jar
|
|
damo> enc hello
|
|
aGVsbG8=
|
|
damo> info
|
|
mode=FAKE revision=20260604 returnCode=0
|
|
damo> quit
|
|
|
|
# 파라미터식: 1회 실행
|
|
java -jar damo-manager.jar enc "hello, 다모"
|
|
java -jar damo-manager.jar dec aGVsbG8sIOuLpOuqqA==
|
|
java -jar damo-manager.jar sha256 password
|
|
|
|
# stdin/stdout 파이프 (text 인자 생략 시 stdin 읽음, 후행 개행 1개 제거)
|
|
echo -n 'hello, 다모' | java -jar damo-manager.jar enc
|
|
echo -n 'hello, 다모' | java -jar damo-manager.jar enc | java -jar damo-manager.jar dec
|
|
|
|
# 기본은 bypass: 모든 동작이 원문 그대로 통과
|
|
java -jar damo-manager.jar enc "hello, 다모" # -> hello, 다모
|
|
|
|
# real/fake 활성화
|
|
java -Ddamo-manager.enabled=true -jar damo-manager.jar enc "hello" # scpdb 있으면 real, 없으면 fake(Base64)
|
|
|
|
# 운영: real 강제 (scpdb 없으면 기동 실패)
|
|
java -Ddamo-manager.require-real=true -jar damo-manager.jar info
|
|
```
|
|
|
|
명령: `enc|encrypt`, `dec|decrypt`, `sha256|hash256`, `sha512|hash512`, `info|mode`, `help|?`, (대화식) `quit|exit`. 알 수 없는 명령은 stderr 안내 후 exit code 2.
|
|
|
|
> 라이브러리로 쓸 때는 manifest 의 `Main-Class` 가 영향을 주지 않는다 (CLI 는 부가 기능).
|
|
|
|
## 소스 코드 커스터마이즈
|
|
|
|
`src/main/java/com/eactive/ext/djb/DamoManager.java` 상단 상수 영역을 수정한다.
|
|
|
|
| 상수 | 의미 | 기본값 |
|
|
|---|---|---|
|
|
| `INI_FILE` | scpdb 에 전달할 ini 경로 | `/prod/damo/ba_scp/scpdb_agent.ini` |
|
|
| `KEY` | `ScpEncB64`/`ScpDecB64` 의 키 이름 | `KEY1` |
|
|
| `CHARSET` | scpdb 호출 시 charset 인자 | `UTF-8` |
|
|
| `SHA256`, `SHA512` | 해시 type 상수 | `71`, `73` |
|
|
|
|
새 scpdb 메서드를 래핑하려면 다음 4 곳을 동기화한다.
|
|
|
|
1. `src/stub/java/com/penta/scpdb/ScpDbAgent.java` — 새 시그니처를 추가 (컴파일 통과용)
|
|
2. `DamoManager.RealBridge` — 실제 호출 메서드 추가
|
|
3. `DamoManager` 공개 메서드 — `if (REAL_MODE) bridge.xxx(...) else fakeXxx(...)`
|
|
4. fake 분기 로직 작성 (보통 Base64 또는 JRE 기능)
|
|
|
|
> Stub 은 `compileOnly` 로만 사용되므로 산출 jar 에 포함되지 않는다. 운영의 진짜 ScpDbAgent 메서드 시그니처와 stub 시그니처가 다르면 운영에서 `NoSuchMethodError` 가 발생하므로 정확히 일치시켜야 한다.
|
|
|
|
## 결과물 사용 방법
|
|
|
|
### 권장: 빌드된 jar 직접 참조
|
|
|
|
타 Gradle 프로젝트에서는 `damo-manager.jar` 를 lib 폴더에 복사하여 직접 참조하는 방식을 권장한다. (Nexus 배포 없이 즉시 사용 가능)
|
|
|
|
**Gradle**:
|
|
|
|
```groovy
|
|
dependencies {
|
|
// 권장. 산출 jar 를 본인 프로젝트의 libs/ 에 복사 후 참조
|
|
compileOnly files('libs/damo-manager.jar')
|
|
// 또는 다른 위치를 직접 가리킨다면
|
|
// compileOnly files('../damo-manager/build/libs/damo-manager.jar')
|
|
}
|
|
```
|
|
|
|
WAS lib 폴더에서 클래스를 로드하므로 의존성 scope 는 반드시 **`compileOnly`** (또는 Maven 의 `provided`) 로 둔다. `implementation`/`api` 로 두면 war 에 중복 포함되어 ClassLoader 충돌 위험.
|
|
|
|
`api` 로 다른 모듈에 노출이 필요하다면 동일하게 `files(...)` 를 `api` scope 로 (단, 위 충돌 가능성 인지).
|
|
|
|
**Maven**:
|
|
|
|
```xml
|
|
<dependency>
|
|
<groupId>com.eactive.ext.djb</groupId>
|
|
<artifactId>damo-manager</artifactId>
|
|
<version>1.0.0</version>
|
|
<scope>system</scope>
|
|
<systemPath>${project.basedir}/libs/damo-manager.jar</systemPath>
|
|
</dependency>
|
|
```
|
|
|
|
또는 사내 Nexus 등에 배포 시 `<scope>provided</scope>`.
|
|
|
|
### WAS (Tomcat) 설치
|
|
|
|
운영 / 로컬에 따라 lib 폴더 구성이 다르다.
|
|
|
|
**운영 (Tomcat)**:
|
|
|
|
```
|
|
$CATALINA_HOME/lib/
|
|
├── damo-manager.jar
|
|
└── libs_scpdb-*.jar ← penta scpdb 라이브러리 (실 암복호화)
|
|
```
|
|
|
|
`libs_scpdb-*.jar` 와 함께 네이티브 .so/.dll 및 `/prod/damo/ba_scp/scpdb_agent.ini` 도 준비되어 있어야 한다.
|
|
**운영 JVM 옵션에 반드시 `-Ddamo-manager.require-real=true` 를 준다** — scpdb 가 빠져 fake/bypass 로 잘못 동작하면 기동 자체가 실패하여 사고를 막는다. (setenv.sh 의 `CATALINA_OPTS`/`JAVA_OPTS` 등)
|
|
|
|
**로컬 개발**:
|
|
|
|
```
|
|
$CATALINA_HOME/lib/
|
|
└── damo-manager.jar ← 단독. scpdb 라이브러리 없음
|
|
```
|
|
|
|
- 옵션 없이 기동 → **bypass**(무변환). 화면/DB 에 원문이 그대로 흐른다.
|
|
- `-Ddamo-manager.enabled=true` 기동 → scpdb 가 없으므로 **fake**(Base64/JRE 해시).
|
|
|
|
WAS 기동 시 콘솔(`catalina.out` 또는 stderr)에 다음 배너 중 하나가 출력된다.
|
|
|
|
```
|
|
# 기본 (옵션 없음)
|
|
============================================================
|
|
*** DAMO-MANAGER BYPASS MODE (default) ***
|
|
암복호화/해시를 전혀 수행하지 않고 원문을 그대로 사용합니다.
|
|
...
|
|
실제 암복호화(real/fake) 가 필요하면: -Ddamo-manager.enabled=true
|
|
============================================================
|
|
|
|
# -Ddamo-manager.enabled=true 인데 scpdb 가 없을 때
|
|
============================================================
|
|
*** DAMO-MANAGER FAKE MODE ***
|
|
com.penta.scpdb.ScpDbAgent NOT FOUND on classpath.
|
|
...
|
|
============================================================
|
|
```
|
|
|
|
real 모드(운영 정상)에서는 배너가 출력되지 않는다.
|
|
|
|
> bypass / fake 모두 암호화가 없으므로 **운영 절대 금지**. 운영은 `-Ddamo-manager.require-real=true` 로 real 을 강제한다.
|
|
|
|
## 주요 메서드
|
|
|
|
```java
|
|
import com.eactive.ext.djb.DamoManager;
|
|
|
|
// 기존 방식 유지
|
|
DamoManager damo1 = new DamoManager();
|
|
|
|
// singleton 필요 시
|
|
DamoManager damo2 = DamoManager.getInstance();
|
|
|
|
String cipher = damo2.encrypt("hello"); // Base64 cipher text
|
|
String plain = damo2.decrypt(cipher); // -> "hello"
|
|
String h256 = damo2.hash(DamoManager.SHA256, "password"); // SHA-256 base64
|
|
String h512 = damo2.hash(DamoManager.SHA512, "password"); // SHA-512 base64
|
|
|
|
boolean fake = damo2.isFakeMode(); // 디버깅 / 분기용 (bypass 면 false)
|
|
boolean bypass = damo2.isBypassMode(); // 기본(옵션 미설정) 이면 true
|
|
int rc = damo2.getReturnCode(); // 0: 성공, -1: 실패
|
|
```
|
|
|
|
`new DamoManager()` 와 `DamoManager.getInstance()` 를 함께 지원하므로,
|
|
기존 호출 코드를 변경하지 않고도 singleton 접근 방식으로 점진 전환할 수 있다.
|
|
|
|
| 메서드 | 운영(real) | Fake | Bypass |
|
|
|---|---|---|---|
|
|
| `String encrypt(String plain)` | `ScpEncB64(INI_FILE, "KEY1", plain, "UTF-8")` | `Base64.encode(plain.getBytes("UTF-8"))` | `plain` (원문) |
|
|
| `String decrypt(String b64)` | `ScpDecB64(INI_FILE, "KEY1", b64, "UTF-8")` | `new String(Base64.decode(b64), "UTF-8")` | 입력 그대로 |
|
|
| `String hash(int type, String src)` | `ScpHashB64(type, src, "UTF-8")` | `MessageDigest(SHA-256/512).digest(src) → Base64` | `src` (원문) |
|
|
|
|
해시 `type` 상수:
|
|
|
|
| 상수 | 값 | 알고리즘 |
|
|
|---|---|---|
|
|
| `DamoManager.SHA256` | 71 | SHA-256 |
|
|
| `DamoManager.SHA512` | 73 | SHA-512 |
|
|
|
|
기타 유틸 (원본 DamoManager 호환):
|
|
|
|
- `Base64Encode(byte[])`, `Base64Decode(String)`
|
|
- `byteToHex(byte[])`, `byteArrayToHex(byte[])`
|
|
- `checkHangul(char)`
|
|
- `getInstance()` (singleton 인스턴스 접근)
|
|
- `getReturnCode()`, `getRevision()`
|
|
- `isFakeMode()`, `isBypassMode()` (현재 모드 판별)
|
|
|
|
## 검증
|
|
|
|
스모크 main 이 포함되어 있다.
|
|
|
|
```bash
|
|
# 기본(bypass)
|
|
java -cp build/libs/damo-manager.jar com.eactive.ext.djb.DamoManager
|
|
# fake (real/fake 활성화, scpdb 부재)
|
|
java -Ddamo-manager.enabled=true -cp build/libs/damo-manager.jar com.eactive.ext.djb.DamoManager
|
|
```
|
|
|
|
또는:
|
|
|
|
```bash
|
|
gradle runBypassSmoke # 기본 bypass
|
|
gradle runFakeSmoke # -Ddamo-manager.enabled=true (fake)
|
|
```
|
|
|
|
예상 출력 (fake 모드, `-Ddamo-manager.enabled=true`):
|
|
|
|
```
|
|
============================================================
|
|
*** DAMO-MANAGER FAKE MODE ***
|
|
...
|
|
============================================================
|
|
|
|
revision = 20260604
|
|
bypassMode = false
|
|
fakeMode = true
|
|
encrypt = aGVsbG8sIOuLpOuqqA==
|
|
decrypt = hello, 다모
|
|
roundtrip = true
|
|
sha256 b64 = ... (len=44)
|
|
sha512 b64 = ... (len=88)
|
|
```
|
|
|
|
기본(bypass) 모드(`gradle runBypassSmoke`, 옵션 없음)에서는 `encrypt`/`decrypt`/`hash` 가 모두 입력(`hello, 다모`)을 그대로 반환하고 `bypassMode = true`, `fakeMode = false` 로 출력된다. `-Ddamo-manager.require-real=true` 인데 scpdb 가 없으면 `ExceptionInInitializerError` 로 기동에 실패한다(운영 보호).
|
|
|
|
### 웹 테스트 페이지 (eapim-admin)
|
|
|
|
eapim-admin 에는 브라우저에서 encrypt/decrypt/hash 를 확인하는 진단 페이지 `WebContent/damo.jsp` 가 있다 (`/monitoring/damo.jsp`, 로그인 필요). damo-manager.jar 를 WAS lib 에 배포하면 현재 모드(REAL/FAKE/BYPASS)와 동작을 즉시 확인할 수 있고, jar 미배포 시에도 안내만 표시하고 깨지지 않는다.
|