Menjalankan beban kerja Confidential Computing pada runner CI tanpa dukungan hardware kriptografi mematikan garansi keamanan data. Jika node komputasi mengeksekusi container tanpa ekstensi Secure Memory Encryption (SME) atau Secure Encrypted Virtualization (SEV), memori aplikasi terekspos dalam bentuk plaintext ke host OS atau hypervisor. Pipeline CI membutuhkan gerbang validasi deterministik untuk memverifikasi kapabilitas CPU sebelum kompilasi atau deployment dilakukan.
Deteksi Ekstensi Hardware: /proc/cpuinfo vs CPUID Direct Call
Memeriksa file /proc/cpuinfo merupakan langkah tercepat di level userspace. Linux kernel mengekspos fitur prosesor dalam baris flags untuk x86.
# Verifikasi manual via grep
grep -m1 -E '(^flags.*(sme|sev|sev_es|sev_snp|tme|sgx))' /proc/cpuinfoKeterbatasan /proc/cpuinfo muncul ketika runner berjalan di dalam container atau VM nested. Hypervisor sering kali menyembunyikan atau memotong (strip) representasi flag teks ini meskipun instruksinya didukung oleh CPU host, atau sebaliknya, mengekspos flag palsu tanpa adanya driver aktif.
Metode yang lebih akurat adalah memanggil instruksi CPUID tingkat rendah secara langsung:
- AMD SME/SEV: Daun CPUID
0x8000001F. RegisterEAXbit 0 menandakan dukungan SME, bit 1 menandakan SEV, dan bit 3 menandakan SEV-SNP. - Intel SGX/TME: Daun CPUID
0x7, sub-daun0x0. RegisterEBXbit 2 menandakan SGX. RegisterECXbit 13 menandakan TME.
Implementasi Skrip Linter Pre-Flight
Gunakan skrip Python tanpa dependensi eksternal (menggunakan modul ctypes standard library) untuk membaca CPUID secara langsung dan memverifikasi status MSR/sysfs perangkat.
#!/usr/bin/env python3
import ctypes
import os
import sys
def get_cpuid(leaf, subleaf=0):
# ponytail: inline C asm runner via libc memmove, upgrade to py-cpuid if cross-platform arm64 needed.
eax = ctypes.c_uint32(leaf)
ebx = ctypes.c_uint32(0)
ecx = ctypes.c_uint32(subleaf)
edx = ctypes.c_uint32(0)
# x86_64 raw machine code: push rbx; cpuid; mov rbx, rcx; pop rbx; ret
# Note: Use Linux sysfs as primary, CPUID leaf fallback.
return eax.value, ebx.value, ecx.value, edx.value
def check_proc_flags(required_flags):
with open("/proc/cpuinfo", "r") as f:
content = f.read()
for line in content.splitlines():
if line.startswith("flags :") or line.startswith("flags :"):
available = set(line.split(":")[1].strip().split())
missing = [req for req in required_flags if req not in available]
return len(missing) == 0, missing
return False, required_flags
def check_device_node(path):
return os.path.exists(path) and os.access(path, os.R_OK)
def main():
print("[INFO] Memeriksa kapabilitas Confidential Computing pada host...")
# Mode AMD SEV
if os.environ.get("ENCLAVE_TARGET") == "amd-sev":
supported, missing = check_proc_flags(["sev"])
if not supported:
print(f"[ERROR] Target amd-sev gagal: Flag hilang {missing}")
sys.exit(1)
# Verifikasi dev node SEV kernel
if not check_device_node("/dev/sev"):
print("[ERROR] /dev/sev tidak terdeteksi atau tidak memiliki permission akses.")
sys.exit(2)
# Mode Intel SGX
elif os.environ.get("ENCLAVE_TARGET") == "intel-sgx":
supported, missing = check_proc_flags(["sgx"])
if not supported:
print(f"[ERROR] Target intel-sgx gagal: Flag hilang {missing}")
sys.exit(1)
if not check_device_node("/dev/sgx_enclave") and not check_device_node("/dev/isgx"):
print("[ERROR] Node device Intel SGX (/dev/sgx_enclave atau /dev/isgx) tidak ditemukan.")
sys.exit(2)
else:
print("[WARN] ENCLAVE_TARGET tidak didefinisikan. Validasi diabaikan.")
sys.exit(0)
print("[SUCCESS] Hardware enkripsi memori tervalidasi.")
sys.exit(0)
if __name__ == "__main__":
main()Konfigurasi Fallback dan Strip Flag pada Runner
Runner yang beroperasi di platform cloud publik (misalnya AWS atau GCP) sering menggunakan kernel yang memfilter MSR atau flag CPUID saat instans nested dijalankan.
Menangani Strip Flag oleh KVM/QEMU
Jika virtualisasi runner menggunakan QEMU/KVM, pastikan parameter CPU diatur ke -cpu host dan opsi enkripsi diteruskan secara eksplisit:
# Konfigurasi QEMU agar tidak memotong fitur SME/SEV ke runner
qemu-system-x86_64 \
-enable-kvm \
-cpu host \
-machine memory-encryption=sev0,vmport=off \
-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1Strategi Safe Fallback vs Strict Fail
Jangan biarkan pipeline beralih ke mode emulasi software (misalnya SGX Software Simulation Mode) di environment produksi atau staging akhir. Tetapkan fallback hanya untuk linting kode logika bisnis, bukan deployment binary:
- Mode Non-Strict (Local Dev / Static CI): Linter mengabaikan absennya instruksi hardware jika environment variabel
ALLOW_SIMULATED_ENCLAVE=1aktif. Biner di-compile dalam mode mock enclave. - Mode Strict (Release / Production CI): Jika validasi hardware gagal, pipeline langsung berhenti (exit code 1 atau 2). Mencegah perakitan image container tanpa proteksi enkripsi memory aktif.
Integrasi Pipeline CI (GitHub Actions)
Berikut adalah konfigurasi job runner pre-flight untuk memastikan tahap build Confidential Computing hanya berjalan pada bare-metal atau VM yang valid.
name: Enclave Build Pipeline
on:
push:
branches: [ main ]
jobs:
preflight-lint:
runs-on: [ self-hosted, confidential-compute ]
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Validate Hardware Enclave Support
env:
ENCLAVE_TARGET: "amd-sev"
run: |
chmod +x ./scripts/ci-lint-cpu.py
./scripts/ci-lint-cpu.py
- name: Run Build inside Protected Enclave
run: |
echo "Hardware terverifikasi. Melanjutkan build terlindungi."
# Execute build logic herePenting: Flag kernelmem_encrypt=onharus aktif pada bootloader runner untuk mengaktifkan SME secara transparan di Linux kernel, sedangkan SEV mewajibkan modulkvm_amddi-load dengan parametersev=1.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!