pqcota

module
v0.6.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: Apache-2.0

README

한국어 · English

pqcota

ci license go

v0.6.5 — Discovery · Inventory · Provisioning 3단계가 리눅스에서 종단으로 동작하고, 데모 6단계가 생성물을 실제 노드에 적용·되돌림까지 확인한다. Windows 노드도 같은 디스커버리 경로로 관측한다(CNG·JCA) — 전환물 생성은 아직이다 → 로드맵

PQC 마이그레이션 관리 플랫폼 pqcota(OSS, Apache-2.0). 레거시 암호 런타임(OpenSSL · Java JCE/JCA)의 PQC 이관을 Discovery → Inventory → Provisioning 3단계로 다룬다.

이름 — pqcota(발음 P-cota) = PQC(양자내성암호) + Orchestra(-ota). 이 소프트웨어는 교향악의 단원이지 마에스트로가 아니다. 무엇을·언제 이관할지 지휘하는 마에스트로는 이 도구를 쓰는 사용자이고, pqcota는 제 파트(관측·정규화·생성)를 정확히 연주한다.

구조를 그림으로 → 플랫폼 구조도

움직이는 것을 보려면 → 시연영상 (2분 55초) — 관측부터 전환물 적용·되돌림까지, 실제 노드에서 ML-KEM이 0개 → 14개 → 0개로 바뀐다.


무엇이 나오나

관측한 것을 노드·앱에 이어 붙이고, 회선에서 실제로 협상된 그룹까지 함께 본다.

──────── ① discovered assets (per node) ────────
  pay-app
    • JCA provider chain: SUN,SunRsaSign,…,BC   [CONFIRMED]
        ↑ 이 BC는 java.security에 한 줄도 없다 (grep 0건).
          앱이 실행 중에 등록한 것이라 정적 스캔으로는 안 보인다.
    • OpenSSL  libcrypto.so.3 3.5.5 (OpenSSL)   [CONFIRMED]
  pay-db
    • OpenSSL  libcrypto.so.1.1 1.1.1f (OpenSSL) [CONFIRMED]

──────── ② observed edges + quantum-resistance grade ────────
  🟢 web-gw  → pay-app   TLS  X25519MLKEM768 [standard]
  🟢 web-gw  → pay-app   SSH  sntrup761x25519-sha512@openssh.com [experimental]
  🔴 web-gw  → pay-db    TLS  x25519
  🔴 web-gw  → pay-db    SSH  curve25519-sha256

  grade totals: 🟢 PQC 2 · 🔴 classical 2 · ⚪ unknown 0

같은 관측을 토폴로지로도 낸다.

🔴는 "취약하다"는 판정이 아니라 "고전 알고리즘으로 협상됐다"는 관측이다. 무엇을 언제 바꿀지는 사용자가 정한다. 전체 예상 출력은 demo/expected-output에 있다.

무엇을 하나 — 세 단계

단계 하는 일 산출
① Discovery 실행 중인 시스템이 어떤 암호 알고리즘을 쓰는지 관측한다 — 로드된 라이브러리, JVM provider 체인, 핸드셰이크에서 협상된 알고리즘 노드별 관측 결과(정규화된 CBOM)
② Inventory 관측을 어느 노드·어느 앱의 것인지 이어 붙여 쌓는다 — 머신 메타데이터, 스냅샷 간 변화 diff 중앙 인벤토리(append-only)
③ Provisioning 확정된 계획에서 PQC 전환 산출물을 만든다 — config 조각, 적용·롤백 Ansible 플레이북(L1/L2/L3), 롤백 근거 플레이북 + before 레코드

하지 않는 것 — 선언(CMDB) 대조·리뷰 확정 거버넌스·플릿 오케스트레이션은 이 리포에 없다. 계약(contracts/)으로 자리만 잡아 두었고, 판정 엔진은 만들지 않는다 — 도구가 대신 판단하면 "🔴는 판정이 아니라 관측"이라는 선이 무너진다. 무엇을 만들고 무엇을 만들지 않았는지의 결정판은 아키텍처 — 명시적 제외/경계다.

써보기 — 데모

Docker만 있으면 전 범위를 한 번에 돌려본다 — 접근준비 → 디스커버리 → 인벤토리 → 프로비저닝(생성·적용·되돌림). 컨테이너로 세운 노드들을 실제로 관측한다.

./demo/scripts/up.sh && ./demo/scripts/demo.sh   # 정리: ./demo/scripts/down.sh

구성·예상 결과·자기 호스트에 적용하는 법 → demo/


사전 요구

빌드

  • Go 1.26.4+
  • buf (+protoc-gen-go·protoc-gen-go-grpc)
  • JDK 11+ — 선택. JVM attach 사이드카를 만들 때만. 없으면 그 단계만 건너뛴다

실행

  • 여러 노드 관측 — 컨트롤러에 Ansible, 대상 노드로의 SSH 접근
  • 단일 노드 관측 — 설치할 것 없음. 그 노드에서 바이너리를 직접 실행한다(pqcota-netcap은 CAP_NET_RAW 필요) → discovery/cmd

빌드

pqcota는 중앙 컨트롤러 노드 하나와, 그 컨트롤러가 Ansible/SSH로 닿는 대상 노드들로 구성된다. 빌드는 컨트롤러에서 한다 — 컨트롤러에서 실행할 CLI와 대상 노드로 보낼 collector를 여기서 함께 만든다.

① 계약 코드 생성 — 계약(contracts/*.proto)에서 Go 코드를 만든다. make tools가 생성 플러그인(protoc-gen-go·-grpc)을 설치하고, make generate가 변환한다. 생성된 gen/은 커밋돼 있다 — 소비자가 go get만으로 계약 타입을 쓰게 하려는 것이다. proto를 고치면 다시 만들어 함께 커밋한다.

make tools && make generate     # contracts/*.proto → gen/

make tools는 플러그인을 $(go env GOPATH)/bin에 넣는데, 그 디렉터리가 PATH에 없으면 make generate가 "플러그인 없음"으로 넘어진다 — 설치가 실패한 것처럼 보이지만 안 보이는 것뿐이다. 두 타깃 모두 그 상황을 짚어 주지만, 셸 설정에 미리 넣어 두면 매번 겪지 않는다: export PATH="$PATH:$(go env GOPATH)/bin".

② 컨트롤러에서 쓸 CLI — 관측 결과를 적재·조회하고 플레이북을 생성하는 커맨드들.

go build -o bin/ ./discovery/cmd/... ./inventory/cmd/... ./provisioning/cmd/...

③ 대상 노드에 올릴 collector — 노드 OS·arch에 맞춰 정적으로 만든다 → 배포 설계. 어느 collector가 어느 OS에서 도는지는 커맨드 레퍼런스.

# 리눅스 노드
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o dist/linux-amd64/ \
  ./discovery/cmd/pqcota-nodescan ./discovery/cmd/pqcota-netcap ./discovery/cmd/pqcota-jvmscan

# Windows 노드
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o dist/windows-amd64/ ./discovery/cmd/pqcota-cngscan

make build-jar                  # JVM 노드가 있을 때만: attach 사이드카 → build/collector.jar

CGO_ENABLED=0(정적 링크 — 배포판·libc 무관)은 고정이고, 바꾸는 것은 GOOS·GOARCH뿐이다. 값 목록은 Go 문서를 따른다.

리눅스 노드의 커널은 3.2 이상이면 된다 — Go 툴체인이 정하는 하한이고, 이 리포가 그보다 새 기능을 요구하지 않는다. CentOS 7(3.10)·Debian 8(3.16)이 위에 있고, RHEL 6(2.6.32)이 아래다. 기능별로 더 필요한 것은 지원 범위에 있다.

노드에서 collector를 돌릴 때의 권한·환경변수 → discovery/cmd.

리포에 기여한다면(테스트·게이트·계약 변경) → CONTRIBUTING.

스택

  • Go — collector·CLI 전부. CGO_ENABLED=0 정적 단일 바이너리
  • Java — JVM attach 사이드카만(JVM 안에서만 가능한 관측이라)
  • Protobuf/gRPC — 단계 사이를 잇는 계약(contracts/)
  • Postgres — 여러 노드를 시간에 걸쳐 쌓고 조회할 때만. 단일 노드 관측에선 쓰지 않는다

무엇을 지원하나 — 단계별

관측 (Discovery)
무엇을 관측 대상 왜
OpenSSL 자산 · 통신 엣지 Linux (amd64·arm64) /proc·ELF·AF_PACKET에 의존
JVM provider 체인 Java 8+ · Linux(전체) · Windows(JDK 있을 때) ①은 리눅스 전용이고 ②·③은 OS 무관이다
Windows CNG provider·알고리즘 Windows (amd64·arm64) bcrypt.dll 열거. 실측 범위는 Windows 11 26200
인벤토리 (Inventory)
무엇을 대상 왜
적재·조회 CLI 어디서든 — Linux · macOS · Windows 파일과 DB만 만진다. OS 프리미티브를 안 쓴다
저장소 Postgres (append-only) 이력·변화를 볼 때만. 한 번 훑는 정도면 pqcota-discover-view가 저장소 없이 낸다
받는 입력 collector의 CollectionResult · CycloneDX 1.6/1.7 CBOM · 사람이 적은 선언 관측 레인과 선언 레인을 섞지 않는다
전환 (Provisioning)

확정 계획의 조치 종류에 따라 갈린다.

런타임 상황 생성물
OpenSSL 3.5+ (네이티브 PQC) config 조각만 — 레거시 무터치
3.0–3.4 provider 모듈 배치 + 그 모듈을 참조하는 config 조각. 모듈 자체는 사용자가 준비한다
1.1.1 이하 생성하지 않는다 — 포크 교체가 필요해 수동 단계로 표기
JCA(Java) JDK 24+ (네이티브 PQC) java.security 조각만. 고전 그룹을 함께 둔다 — 릴리스 JDK가 아직 하이브리드 그룹을 협상하지 않는다(≤25 실측)
JDK 8+ (provider 주입) provider JAR 배치 + java.security 등록 조각. JAR 배치만으로는 로드되지 않아 활성화가 따로 필요하다
그 이하(EOL) 생성하지 않는다 — JDK 업그레이드가 필요해 수동 단계로 표기

적용은 Ansible 플레이북으로 한다. 생성되는 플레이북이 POSIX 경로·모듈(ansible.builtin.copy, /opt/pqcota)을 전제하므로 대상 노드는 Linux다 — Ansible 자체는 Windows도 다루지만 이 산출물이 아직 그렇지 않다.

Windows(CNG)는 관측된다(pqcota-cngscan). 전환물 생성은 substrate 일반화가 선행이라 로드맵에 있다.


상태 · 버전

릴리스마다 arch별 정적 바이너리와 SHA256SUMS가 릴리스에 붙는다. 받은 뒤 sha256sum -c SHA256SUMS로 확인한다. 서명된 릴리스는 로드맵에 있다. 버전별 목표·성과는 릴리스 노트.

라이선스

Directories

Path Synopsis
demo
topology/topogen command
Command topogen — demo/topology/topology.yaml → 데모 산출물 생성기.
Command topogen — demo/topology/topology.yaml → 데모 산출물 생성기.
workloads/pqc-echo command
Command pqc-echo — 데모용 PQC TLS 트래픽 생성기(🟢 엣지).
Command pqc-echo — 데모용 PQC TLS 트래픽 생성기(🟢 엣지).
discovery
cmd/internal/localview
Package localview — 수집 결과를 **그 자리에서** 사람이 읽는 뷰로 렌더한다.
Package localview — 수집 결과를 **그 자리에서** 사람이 읽는 뷰로 렌더한다.
cmd/pqcota-cngscan command
Command pqcota-cngscan — 타깃(Windows) 노드에서 실행.
Command pqcota-cngscan — 타깃(Windows) 노드에서 실행.
cmd/pqcota-hosts command
Command pqcota-hosts — 사용자 관리 hosts 파일(CSV)을 읽어 discovery 접근을 준비한다(§1.5).
Command pqcota-hosts — 사용자 관리 hosts 파일(CSV)을 읽어 discovery 접근을 준비한다(§1.5).
cmd/pqcota-jvmscan command
Command pqcota-jvmscan — 타깃(Java) 노드에서 실행.
Command pqcota-jvmscan — 타깃(Java) 노드에서 실행.
cmd/pqcota-keygen command
Command pqcota-keygen — collector 리포트 서명용 ed25519 키쌍을 생성한다(§2.6).
Command pqcota-keygen — collector 리포트 서명용 ed25519 키쌍을 생성한다(§2.6).
cmd/pqcota-netcap command
Command pqcota-netcap — 타깃 노드에서 실행.
Command pqcota-netcap — 타깃 노드에서 실행.
cmd/pqcota-nodescan command
Command pqcota-nodescan — 타깃 노드에서 실행.
Command pqcota-nodescan — 타깃 노드에서 실행.
cmd/pqcota-procs command
Command pqcota-procs — 타깃 노드에서 실행.
Command pqcota-procs — 타깃 노드에서 실행.
collectors/cng
Package cng — Windows CNG(Cryptography Next Generation) collector.
Package cng — Windows CNG(Cryptography Next Generation) collector.
collectors/jvm
Package jvm hosts the JVM collector's Go side: it parses the Java attach sidecar 출력을 정규화된 CBOM Envelope(CollectionResult)로 변환하고 intake 계약(§1.6)으로 노출한다.
Package jvm hosts the JVM collector's Go side: it parses the Java attach sidecar 출력을 정규화된 CBOM Envelope(CollectionResult)로 변환하고 intake 계약(§1.6)으로 노출한다.
collectors/network
Package network implements the network-collector (디스커버리 설계 §2.5) — TLS/SSH 핸드셰이크를 수동 관측해 협상된 KEX 그룹과 통신 엣지를 잡는다.
Package network implements the network-collector (디스커버리 설계 §2.5) — TLS/SSH 핸드셰이크를 수동 관측해 협상된 KEX 그룹과 통신 엣지를 잡는다.
collectors/openssl
Package openssl implements the OpenSSL runtime collector (설계 문서 §2.1, SD-1·SD-3).
Package openssl implements the OpenSSL runtime collector (설계 문서 §2.1, SD-1·SD-3).
collectors/openssl/integration/probe command
Command openssl-collector — PoC/CLI.
Command openssl-collector — PoC/CLI.
gen
inventory
cmd/pqcota-cbom-ingest command
Command pqcota-cbom-ingest — 외부(CBOMkit 등) CycloneDX CBOM을 수신·검증·적재한다(SV-2·SD-7).
Command pqcota-cbom-ingest — 외부(CBOMkit 등) CycloneDX CBOM을 수신·검증·적재한다(SV-2·SD-7).
cmd/pqcota-declare command
Command pqcota-declare — 사용자 선언 인벤토리(CMDB/CSV)를 선언 레인 CollectionResult로 임포트한다(§2.3, SV-1).
Command pqcota-declare — 사용자 선언 인벤토리(CMDB/CSV)를 선언 레인 CollectionResult로 임포트한다(§2.3, SV-1).
cmd/pqcota-declare-attribution command
Command pqcota-declare-attribution — 사람이 지정한 **엣지의 앱**을 선언 레인으로 임포트한다.
Command pqcota-declare-attribution — 사람이 지정한 **엣지의 앱**을 선언 레인으로 임포트한다.
cmd/pqcota-discover-view command
Command pqcota-discover-view — OSS 읽기전용 디스커버리 인벤토리 뷰(설계 §5 "읽기전용 인벤토리 뷰").
Command pqcota-discover-view — OSS 읽기전용 디스커버리 인벤토리 뷰(설계 §5 "읽기전용 인벤토리 뷰").
cmd/pqcota-ingest command
Command pqcota-ingest — 중앙(인벤토리 호스트)에서 실행.
Command pqcota-ingest — 중앙(인벤토리 호스트)에서 실행.
cmd/pqcota-inventory command
Command pqcota-inventory — 중앙에서 실행.
Command pqcota-inventory — 중앙에서 실행.
cmd/pqcota-profile command
Command pqcota-profile — CMDB/사용자 프로필 CSV를 인벤토리 머신 프로필로 임포트한다(§2.0).
Command pqcota-profile — CMDB/사용자 프로필 CSV를 인벤토리 머신 프로필로 임포트한다(§2.0).
cmd/pqcota-prune command
Command pqcota-prune — 보존 정책 집행(오래된 변화 지점 절단).
Command pqcota-prune — 보존 정책 집행(오래된 변화 지점 절단).
pkg
discovery/history
Package history is the append-only discovery history (규정서 §2.4⑥, §1.2 원본 불변).
Package history is the append-only discovery history (규정서 §2.4⑥, §1.2 원본 불변).
discovery/normalize
Package normalize implements the Discovery normalization pipeline (규정서 §2.4).
Package normalize implements the Discovery normalization pipeline (규정서 §2.4).
discovery/procs
Package procs — app → 라이브 프로세스 실시간 해소 (자산 모델 §1.5, ProcessMatch).
Package procs — app → 라이브 프로세스 실시간 해소 (자산 모델 §1.5, ProcessMatch).
inventory
Package inventory renders the read-only inventory view (인벤토리 설계 §1 컴포넌트 아키텍처, Phase 0 산출물).
Package inventory renders the read-only inventory view (인벤토리 설계 §1 컴포넌트 아키텍처, Phase 0 산출물).
inventory/declaration
Package declaration implements the declaration importer (설계 §2.4, SV-1).
Package declaration implements the declaration importer (설계 §2.4, SV-1).
inventory/ingest
Package ingest implements the CBOM import adapter (설계 문서 §2.3, SV-2·SD-7).
Package ingest implements the CBOM import adapter (설계 문서 §2.3, SV-2·SD-7).
kernel/machineid
Package machineid — 머신 상관 지문 수집 + 자동 UID(self-id) 결정론적 부여 (규정서 §1.4).
Package machineid — 머신 상관 지문 수집 + 자동 UID(self-id) 결정론적 부여 (규정서 §1.4).
kernel/posture
Package posture classifies a negotiated key-exchange group into a quantum-resistance posture (인벤토리 설계 §6.1).
Package posture classifies a negotiated key-exchange group into a quantum-resistance posture (인벤토리 설계 §6.1).
kernel/registry
Package registry holds deterministic signature-matching data used by the Discovery enrichment stage (수용 원칙 §2.3, 설계 문서 §3.3).
Package registry holds deterministic signature-matching data used by the Discovery enrichment stage (수용 원칙 §2.3, 설계 문서 §3.3).
kernel/scope
Package scope implements the scope-master gate (규정서 §1.4).
Package scope implements the scope-master gate (규정서 §1.4).
kernel/sign
Package sign implements collector 리포트 서명·검증 (규정서 §2.6 — provenance).
Package sign implements collector 리포트 서명·검증 (규정서 §2.6 — provenance).
org
Package org — 인벤토리의 조직 축.
Package org — 인벤토리의 조직 축.
provisioning
Package deploy generates collector deployment artifacts (설계 §2.4 배포 티어).
Package deploy generates collector deployment artifacts (설계 §2.4 배포 티어).
provisioning
cmd/pqcota-provision command
Command pqcota-provision — 확정 계획(FinalizedPlan JSON)에서 프로비저닝 산출물을 만든다:
Command pqcota-provision — 확정 계획(FinalizedPlan JSON)에서 프로비저닝 산출물을 만든다:
cmd/pqcota-records command
Command pqcota-records — 영속된 프로비저닝 레코드(롤백 근거)를 조회한다(§6A).
Command pqcota-records — 영속된 프로비저닝 레코드(롤백 근거)를 조회한다(§6A).
tools
checkdocs command
Command checkdocs — 문서 게이트.
Command checkdocs — 문서 게이트.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL