RUNBOOK Sigil 배포 / 테스트
flowchart LR
subgraph mac["Mac — agent 호스트 · inbound 포트 없음"]
direction TB
agent["sigil (agent)"]
spool[("JSONL spool")]
sender["sigil-sender"]
agent -->|"watch·hash·JSONL"| spool
spool -->|reads| sender
sender -.->|"apply_policy (UDS·로컬)"| agent
end
subgraph vm["Rocky VM · bridged"]
server["sigil-server :8443"]
store[("events_out_dir · host_id별 JSONL")]
server --> store
end
sender ==>|"mTLS 8443 · 이벤트 push"| server
server -.->|"mTLS 8443 · 서명정책 pull (ETag)"| sender
classDef comp fill:#d1fae5,stroke:#059669,color:#064e3b;
class agent,spool,sender,server comp;
sigil-sender 가 전담 → server 로 outbound./v1/* 엔드포인트 (data + control + read API 동일 bind).| 컴포넌트 (호스트) | 방향 | 포트 | 프로토콜 | 용도 | 상대 |
|---|---|---|---|---|---|
| sigil-server (서버 VM) | inbound | 8443/tcp ( bind 설정값) | TLS (mTLS) | POST /v1/events 수신 · GET /v1/policy 서빙 · /v1/healthz · /v1/meta+read API — 전부 같은 포트 | agent 호스트들, (옵션) sigil-manager / 운영자 |
| agent 호스트 (Mac/엔드포인트) | outbound | 8443/tcp | TLS | sigil-sender → server (이벤트 push + 정책 pull) | → sigil-server |
| agent 호스트 | outbound | 443/tcp 또는 SIEM 포트 (예: Splunk HEC 8088) | TLS | sigil-sender → SIEM 직접 경로 쓸 때만 | → SIEM |
| agent ↔ sender | 로컬 | 네트워크 포트 없음 | Unix socket | apply_policy IPC (같은 호스트) | n/a |
| (옵션) sigil-manager | outbound | 8443/tcp | TLS+bearer | server read API(/v1/meta, fleet) 조회 | → sigil-server |
| (옵션) sigil-manager | inbound | 자체 웹 포트 (예: 8080) | TLS | fleet 웹 콘솔 | 운영자 브라우저 |
요점. ① 서버만 inbound 1개(8443) 열면 끝. ② agent 호스트는 inbound 0개 — 리슨 포트 없음, outbound 만 (lockdown 된 엔드포인트 fleet 에 유리). ③ agent↔sender 는 로컬 UDS 라 방화벽 무관.
인증 계층 구분: data/control 경로(/v1/events, /v1/policy)는 mTLS 클라이언트 cert 로 인증. read API(/v1/meta, fleet)는 그 위에 bearer 토큰 게이트(Phase 3b.4) — 토큰 미설정이면 404. /v1/healthz 만 인증 없음(단 여전히 mTLS 핸드셰이크는 필요).
데모 demo/init.sh 의 openssl 묶음 그대로, server cert 의 SAN 만 조정.
# CA
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-keyout ca.key -out ca.crt -subj "/CN=sigil-test-ca" \
-addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign"
# 서버 cert — SAN 에 hostname(권장) + IP. sender 가 접속할 주소가 SAN 에 있어야 함.
cat > server.ext <<'EOF'
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:sigil-server, IP:192.168.0.50
EOF
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=sigil-server"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 \
-extfile server.ext -out server.crt
# 클라이언트(sender) cert
cat > client.ext <<'EOF'
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature
extendedKeyUsage = clientAuth
EOF
openssl req -new -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj "/CN=mac-sender"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 \
-extfile client.ext -out client.crt
정책 서명 키 + keystore + signed bundle (control-plane 용; data-plane 만 볼 거면 생략 가능):
sigil-sign keygen --id test-key --out signing-key.json
PUB=$(jq -r .ed25519_pubkey_b64 signing-key.json)
cat > policy-signing-pubkeys.pem <<EOF
{ "pubkeys": [ { "id":"test-key","ed25519_pubkey_b64":"$PUB","valid_from":"2020-01-01T00:00:00Z","valid_until":"2099-01-01T00:00:00Z" } ] }
EOF
cp config/policy.example.yaml policy.yaml
sigil-sign sign --in policy.yaml --key signing-key.json \
--policy-version 2 --valid-until 2099-01-01T00:00:00Z --out signed-policy.json
ARM64 주의. Apple Silicon Mac 의 VM 은 aarch64. prebuilt/x86_64 rpm 은 안 됨(cross-arch 패키징 미구현 — open issue #12). VM 에서 소스 빌드가 정답.
# Rocky aarch64 — 소스 빌드
sudo dnf install -y gcc git
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh && source "$HOME/.cargo/env"
git clone https://github.com/Ju571nK/sigil && cd sigil
cargo build --release -p sigil-server # → target/release/sigil-server (네이티브 aarch64)
sudo mkdir -p /etc/sigil-server /var/lib/sigil-server/events
# A에서 만든 것 전송: server.crt server.key ca.crt signed-policy.json
sudo cp server.crt server.key ca.crt signed-policy.json /etc/sigil-server/
/etc/sigil-server/server.yaml:
bind: "0.0.0.0:8443"
events_out_dir: "/var/lib/sigil-server/events"
policy_bundle_path: "/etc/sigil-server/signed-policy.json"
tls_cert_path: "/etc/sigil-server/server.crt"
tls_key_path: "/etc/sigil-server/server.key"
client_ca_path: "/etc/sigil-server/ca.crt" # ← 3개 다 켜야 mTLS ON (안 켜면 PLAIN HTTP 경고)
# 방화벽 (Rocky/firewalld)
sudo firewall-cmd --add-port=8443/tcp --permanent && sudo firewall-cmd --reload
# SELinux enforcing 면: 8443 은 보통 http_port_t 에 포함. 커스텀 포트 쓰면:
# sudo semanage port -a -t http_port_t -p tcp <port>
# 실행
./target/release/sigil-server serve --config /etc/sigil-server/server.yaml
ip addr | grep 192.168 # VM 의 LAN IP 확인 (bridged 면 LAN 대역)
echo "192.168.0.50 sigil-server" | sudo tee -a /etc/hosts # hostname SAN 매핑
mkdir -p ~/sigil-test/{events,state,run}
# 소스 빌드 (Apple Silicon = aarch64-apple-darwin 네이티브)
cargo build --release -p sigil-agent -p sigil-sender
# A에서: ca.crt client.crt client.key policy-signing-pubkeys.pem policy.yaml 가져오기
~/sigil-test/sender.yaml:
server_base_url: "https://sigil-server:8443"
client_cert_path: "/Users/ju571nk3n/sigil-test/client.crt"
client_key_path: "/Users/ju571nk3n/sigil-test/client.key"
server_ca_path: "/Users/ju571nk3n/sigil-test/ca.crt"
events_dir: "/Users/ju571nk3n/sigil-test/events"
offset_path: "/Users/ju571nk3n/sigil-test/state/sender-offset.json"
agent_control: "/Users/ju571nk3n/sigil-test/run/control.sock"
dead_letter_dir: "/Users/ju571nk3n/sigil-test/events/dead-letter"
policy_poll_interval: 10
# 터미널 1 — agent (events-dir / control 경로를 sender.yaml 과 일치)
./target/release/sigil run --policy ~/sigil-test/policy.yaml \
--events-dir ~/sigil-test/events --state-db ~/sigil-test/state/state.db
# 터미널 2 — sender
./target/release/sigil-sender --config ~/sigil-test/sender.yaml start
경로 정합이 핵심. sender 의 events_dir/agent_control 는 Mac agent 의 실제 events·control 경로와 같아야 함. agent 의 control socket override 플래그가 없으면 sigil show config 로 실제 경로를 확인하고 sender.yaml 을 맞추세요.
# Mac → VM mTLS 도달 (인증 없는 healthz, 단 클라이언트 cert 는 필요)
curl --cacert ca.crt --cert client.crt --key client.key https://sigil-server:8443/v1/healthz
# Mac 의 watch 대상 한번 건드리기 (예시)
touch ~/.claude/settings.json # 또는 policy.yaml 의 targets 경로
# VM: host_id 별 JSONL 이 생기는지
ls -R /var/lib/sigil-server/events
/v1/meta·fleet 등 read API 는 bearer 토큰이 설정돼 있어야 200 (없으면 404). reachability 확인은 /v1/healthz 로.
bind 로 포트 변경 가능. 엔드포인트 fleet 는 egress-only(서버:8443 로 나가는 것만 허용) — agent 호스트엔 inbound 룰 불필요.not_after · audit/이벤트 timestamp 가 시계에 의존. 양쪽 skew 크면 TLS 만료·서명 검증 오판.server_base_url 은 FQDN. (테스트만 /etc/hosts.)/var/lib/sigil-server 쓰기에 라벨 필요할 수 있음. sigil doctor 가 SELinux·소켓 perms·systemd·events 디렉터리 4-check 로 점검.host_allowlist_path(JSON {"hosts":["uuid",...]})로 수용 host_id 제한 가능.server_base_url 을 SIEM HTTPS 엔드포인트로 — 그 경우 열 포트는 SIEM 쪽 규격(예 Splunk HEC 8088, 일반 443).curl timeout. bridged 로 VM 이 LAN IP 받게.DNS:sigil-server(+/etc/hosts) 또는 IP:192.168.0.50.127.0.0.1 바인드 → 외부 도달 불가. 0.0.0.0:8443 + firewalld 허용.이 문서는 테스트/배포 레퍼런스 (repo 미커밋, 본인 환경값 포함). 차트는 mermaid (CDN 렌더) — 오프라인이면 차트 소스가 텍스트로 보이고, GitHub/IDE preview 에서는 렌더됨. 일반화해서 정식 배포 doc 로 넣고 싶으면 IP/경로를 placeholder 로 바꿔 커밋하면 됩니다.