제 7 장 보안 모델
Fayger 의 보안 모델은 두 갈래로 구성됩니다:
- 출처 신뢰: BuF 산출물 자체에 서명할 수 있고, 적재 시 출처와 무결성을 검증합니다.
- 실행 통제: BuF_Instance 는 실행 중 명시적으로 부여된 권한만 사용할 수 있고, 선언되지 않은 권한은 일절 보이지 않습니다.
두 갈래는 각각 로더 계층과 어댑터 계층에 자리 잡고, 제 6 장의 오류 모델과 제 4 장의 장애 격리에서 보강됩니다.
7.1 출처 신뢰: 서명과 다이제스트
다이제스트
각 Section 은 BuF_Manifest 에 digest 를 선언합니다. 적재 사슬의 Verify Digest 단계에서 각 Section 의 다이제스트를 다시 계산하여 비교:
- 어느 단이라도 불일치면
LDR_DIGEST_MISMATCH반환. - 오류 context 는 실패한
section_id포함.
Trailer 의 manifest_digest 는 동시에 Manifest 자체가 잘리거나 수정되지 않았음을 검증합니다.
서명 범위
서명이 커버하는 바이트 범위:
Header || Manifest_minus_signature || Section_Index
설계 의도:
- 공격자가 서명 후 Manifest 의 어떤 필드(signature 블록 자체 제외)라도 수정하면 서명이 무효화됩니다.
- Section 오프셋, 길이, 다이제스트의 변경도 서명을 무효화합니다(Section_Index 가 서명 범위 내이기 때문).
- Section 본체 자체는 서명 범위 내에 직접 포함되지 않으나, 각 단의
digest가 Manifest 내에 있어 간접적으로 커버됩니다.
이 "manifest 에 서명, digest 가 sections 를 연쇄" 방식은 OCI Image 서명과 같은 절충: 서명 입력 크기는 통제 가능하고 검증 속도는 예측 가능합니다.
지원 서명 알고리즘 (1 단계)
ed25519ecdsa-p256rsa-pss-sha256
알고리즘 식별자와 공개 키 참조는 모두 Manifest 의 signature 블록에서 명시 선언하여, ASN.1 / X.509 기반 암묵적 협상을 피합니다.
서명 검증 결정표
| 조건 | 기대 결과 |
|---|---|
| 강제 서명 ON ∧ 서명 없음 | Err(LDR_SIGNATURE_FAIL), 사유 MissingSignature |
| 서명 있음 ∧ 검증 실패 | Err(LDR_SIGNATURE_FAIL), 사유 InvalidSignature |
| 서명 있음 ∧ 검증 통과 | Ok |
| 강제 서명 OFF ∧ 서명 없음 | Ok (개발 편의) |
7.2 강제 서명 모드
강제 서명 모드(enforce signature)는 LoaderPolicy.require_signature 가 통제하는 적재 정책 스위치입니다:
struct LoaderPolicy {
require_signature: bool
trusted_roots: TrustedRootSet
allowed_schema_versions: VersionRange
}
행위 제약:
- 켜짐: 어떤 BuF 도 서명을 가지고 검증을 통과해야 하며, 그렇지 않으면 적재 거부.
- 꺼짐: 서명 없는 BuF 도 적재 가능(개발 편의), 서명을 가졌으나 무효한 BuF 는 여전히 거부("서명한 척" 을 허용하지 않음).
릴리스 시나리오(프로덕션, 신뢰 가능 배포 채널)에서는 설정 계층에서 require_signature 를 기본 true 로 두기를 권장합니다.
7.3 신뢰 루트 관리
interface TrustStore {
current_roots() -> TrustedRootSet
update(roots: TrustedRootSet)
enforce_signature() -> bool
}
업데이트 가시성 제약:
- 작업 시퀀스
Ops(Update(roots)와Load(buf)의 혼합)에 대해, 매Load(buf)가 서명 검증에 사용하는 신뢰 루트 집합은 그 Load 직전 마지막Update가 설정한 roots 와 같아야 합니다. - 이 제약은 "적재 도중 root 집합이 바뀌는" 경합을 의미상 불가능하게 만듭니다.
구현 전략:
- 매
LoaderPipeline.load입구에서TrustStore의 스냅샷을 찍고, 해당 적재 전체가 그 스냅샷을 사용. - 적재 기간 동안 가변 신뢰 루트 집합의 공유를 명시적으로 거부.
7.4 실행 통제: 권한 보안 모델
어댑터 계층은 capability-based security(WASI 와 동일)를 채택합니다. BuF 는 Manifest 에서 권한 요청을 선언하고, Platform_Adapter 와 호스트 정책이 공동으로 부여를 결정합니다.
형식:
granted = requested ∩ available ∩ host_policy
denied = requested \ granted
시작 게이트
manifest.required_capabilities \ granted ≠ ∅ 인 경우:
start()는 반드시 오류 반환.- 오류 context.missing 은 차집합과 같음.
- 인스턴스는 Running 으로 진입하지 않음.
이는 "권한 부족 시 시작 금지" 의 단단한 제약입니다.
기본 거부
- 선언되지 않은 권한은 BuF 에 보이지 않습니다.
- Platform_Adapter 는 "어쨌든 비트가 그럴듯하니 통과" 같은 식으로 선언되지 않은 권한을 제공해서는 안 됩니다.
- 인식되지 않은 Universal_Instruction 카테고리는 일률
ADP_UNSUPPORTED_INSTRUCTION을 반환하며 "조용한 통과" 가 없습니다.
7.5 권한 분류와 축소 요점 (호스트별)
| 호스트 클래스 | 전형적 사용 가능 | 전형적 사용 불가 | 비고 |
|---|---|---|---|
| 데스크톱 | io.*, net.*, ui.*, time, random, crypto, proc.*, host.* | 플랫폼과 권한에 따름 | 권한 거의 전체 집합 |
| 서버 | io.*, net.*, time, random, crypto, proc.* | ui.* 전부 비활성 | GUI 없음이 기본 |
| 브라우저 | net.fetch, net.websocket, ui.dom, time, random, crypto 의 부분 | proc.*, 대부분의 io.* | 강한 축소 |
| In-App | 호스트가 명시 주입 | 기본 전부 비활성 | 가장 엄격, 호스트가 최종 결정권 |
7.6 보안 장벽으로서의 리소스 격리
리소스 격리는 안정성 요구이자 보안 장벽의 일부입니다:
- 단일 BuF_Instance 의 장애가 다른 인스턴스로 전파되지 않습니다(제 4 장 장애 격리 성질).
- 쿼터 초과는 일시 정지를 유발하여 한 인스턴스가 호스트 자원을 소진하는 것을 방지합니다.
- 인스턴스 간 RuntimeDataArea 는 상호 불가시이며, 데이터 계층에서 사이드 채널 정보 누설을 방지합니다.
7.7 보안 / 오류의 상호작용
서명과 권한 관련 실패는 통일 오류 모델로 외부에 반환됩니다:
- 서명 실패:
LDR_SIGNATURE_FAIL,MissingSignature/InvalidSignature등 사유 포함. - 권한 거부:
ADP_CAPABILITY_DENIED, 거부된 권한 집합 포함. - 시작 게이트 실패:
ADP_CAPABILITY_DENIED재사용. context.missing 에 차집합.
오류 체인은 제 6 장과 일치: 하위 계층 오류는 cause 에, 상위 계층 오류는 자신의 source_layer 를 표시. 호출자는 체인을 따라 위치를 파악할 수 있습니다.
7.8 보안 감사 권장
감사 자체는 Fayger 의 내부 범위가 아니지만, Fayger 의 이벤트 버스, Lifecycle 이벤트, Loader 이벤트는 외부 감사 시스템에 충분한 앵커를 제공합니다:
- 적재 사슬 각 단계의 성공 / 실패 이벤트는 출처 검증의 감사 지점.
- Lifecycle 이벤트는 각 인스턴스의 시작 / 일시 정지 / 종료 시간선 기록.
- 권한 축소 결과는 보안 결정의 감사 지점.
- 서명 실패, 권한 거부, 쿼터 초과 이벤트는 외부 SIEM / 감사 파이프라인에서 구독 가능.
