💭 Minji's Archive

[s2n] devlog - CLI 입력 데이터 구조 리팩토링 (CLIArguments -> ScanRequest)

November 09, 2025

1. 개요

cli.py에서 개별적으로 처리되고 있는 CLI 옵션들을 공통 인터페이스 계층의 타입 구조를 활용해 통합된 입력 데이터 플로우로 정리한다.

  • 기존: click -> dict -> Scanner
  • 변경: click -> CLIArguments -> ScanRequest -> ScanConfig -> Scanner

이를 통해 CLI, python import, rest api 호출이 모두 동일한 입력 타입 체계를 사용하게 된다.

2. 배경 및 문제점

현재 cli.py는 Click의 옵션 인자를 바로 함수 내부에서 처리하고 있다. 이 구조는 직관적이지만, CLI 실행 외의 환경(Python SDK, REST API, 테스트 코드 등)에서는 재사용이 어렵다.

3. 개선 방향

click options
    ↓
CLIArguments
    ↓ (검증/변환)
ScanRequest
    ↓ (구성 단계)
ScanConfig
    ↓
Scanner 실행
  • CLIArguments: CLI에서 입력받은 인자를 구조화
  • ScanRequest: 인자를 표준 스캔 요청으로 변환
  • ScanConfig: 실제 Scanner 엔진 실행 설정
  • Scanner: 스캔 실행, 플러그인 호출

4. 변환 로직 설계

(1) CLIArguments -> ScanRequest 변환

core/s2nscanner/cli/mapper.py 생성

#### (2) ScanRequest -> ScanConfig 변환 core/s2nscanner/cli/config_builder.py 생성

(3) CLI 통합 예시

cli.py의 scan 명령은 아래와 같이 단순화될 것이다.

@cli.command("scan")
@click.option("-u", "--url", required=True)
@click.option("-p", "--plugin", multiple=True)
@click.option("-a", "--auth")
@click.option("--username")
@click.option("--password")
@click.option("-o", "--output")
@click.option("-v", "--verbose", is_flag=True)
@click.pass_context
def scan(ctx, url, plugin, auth, username, password, output, verbose):
    from s2n.s2nscanner.cli.mapper import cliargs_to_scanrequest
    from s2n.s2nscanner.cli.config_builder import build_scan_config

    # 1️⃣ CLIArguments 생성
    args = CLIArguments(
        url=url,
        plugin=list(plugin),
        auth=auth,
        username=username,
        password=password,
        output=output,
        verbose=verbose
    )

    # 2️⃣ ScanRequest 변환
    request = cliargs_to_scanrequest(args)

    # 3️⃣ ScanConfig 생성
    config = build_scan_config(request)

    # 4️⃣ 스캐너 실행
    scanner = Scanner(config=config, logger=ctx.obj["logger"])
    report = scanner.scan()

    # 5️⃣ 결과 출력
    print(f"총 발견된 취약점: {len(report.summary.severity_counts)}개")