본문으로 건너뛰기

개발 가이드

BioStar X와 연동되는 플러그인의 실제 개발 방법과 구현 예시를 안내합니다.

필수 엔드포인트 구현

BioStar X와 연동되는 플러그인을 개발하려면 다음 두 개의 엔드포인트를 반드시 구현해야 합니다. 이 문서에서는 /bsx를 예시 경로로 사용합니다.

플러그인 등록 엔드포인트

GET /bsx

플러그인을 등록할 때 BioStar X Service Manager에서 서버 접근성을 확인하기 위해 호출하는 엔드포인트입니다.

요청 형식

GET /bsx
Headers:
X-BioStar-Ping: <ping_token>

구현 요구 사항

Python FastAPI
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.get("/bsx")
async def bsx_ping(request: Request):
"""BioStar X 플러그인 등록용 ping 엔드포인트"""
ping_token = request.headers.get("x-biostar-ping")
# 응답에 ping 토큰 반환
response_data = {"token": ping_token}
response = JSONResponse(content=response_data)
return response

응답 형식

Success (200 OK)
{
"token": "<ping_token_value>"
}

테스트

curl 명령어를 사용해 수동으로 엔드포인트를 테스트할 수 있습니다.

curl -H "X-BioStar-Ping: test123" http://localhost:8000/bsx

사용자 인증 콜백 엔드포인트

POST /bsx

사용자가 BioStar X 웹 인터페이스에서 플러그인 아이콘을 클릭할 때 호출되는 엔드포인트입니다. 이 과정에서 BioStar X에 로그한 사용자의 세션(session)을 요청해 응답을 받습니다.

알아두기

BioStar X와 플러그인 간의 보안 통신을 위해 인증서가 필요합니다. 인증서는 플러그인 등록 후 해당 플러그인 상세 페이지에서 다운로드할 수 있습니다. 자세한 내용은 다음 문서를 참고하세요.

요청 형식

POST /bsx
Content-Type: application/x-www-form-urlencoded

user_id={user_id}&plugin_id={plugin_id}

구현 요구사항

  1. 매개변수 검증: user_idplugin_id 필수 값 확인

  2. AES 키 생성: 보안 통신용 32바이트 키 생성

  3. 키 암호화: RSA 공개키로 AES 키 암호화(예시 코드에서는 public_key.pem 파일 이름으로 가정)

  4. 세션 브리지 요청: BioStar X 서버에 세션 요청

  5. 세션 복호화: 받은 암호화된 세션 ID를 AES로 복호화

import uuid
import requests
from fastapi import HTTPException, Form

@app.post("/bsx")
async def bsx_callback(
request: Request,
user_id: str = Form(None, description="사용자 ID"),
plugin_id: str = Form(None, description="플러그인 ID")
):
"""BioStar X 플러그인 콜백 처리"""
# 1. 필수 매개변수 검증
if not user_id:
raise HTTPException(status_code=400, detail="user_id가 필요합니다")
if not plugin_id:
raise HTTPException(status_code=400, detail="plugin_id가 필요합니다")

# 2. 보안 통신을 위한 AES 키 생성
key = uuid.uuid4().hex # 32바이트 키

# 3. RSA 공개키로 키 암호화
encrypted_key = encrypt_with_public_key(key, "public_key.pem")

# 4. BioStar 서버에 세션 브리지 요청
payload = {
"user_id": user_id,
"plugin_id": plugin_id,
"key": encrypted_key
}

response = requests.post(
f"https://{BIOSTAR_SERVER}/api/session/bridge",
json=payload,
verify=False
)

# 5. 응답 처리
if response.status_code == 200:
data = response.json()
if data.get("Response", {}).get("code") == "0":
# 세션 ID 복호화
encrypted_session = data.get("bs_session_id")
bs_session_id = decrypt_aes256_base64(encrypted_session, key)
else:
# BioStar X 오류 처리
error_msg = data.get("Response", {}).get("message", "알 수 없는 오류")
raise HTTPException(status_code=400, detail=f"BioStar X 오류: {error_msg}")
else:
raise HTTPException(status_code=500, detail="BioStar X 서버 연결 실패")

테스트

curl 명령어를 사용해 수동으로 엔드포인트를 테스트할 수 있습니다.

curl -X POST http://localhost:8000/bsx \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "user_id={user_id}&plugin_id={your_plugin_id}"

암호화 구현

다음 암호화 함수를 구현해야 합니다.

RSA 공개키 암호화

from cryptography.hazmat.primitives import serialization, padding
import base64

def encrypt_with_public_key(message: str, public_key_path: str) -> str:
"""RSA 공개키로 메시지 암호화"""
with open(public_key_path, 'rb') as key_file:
public_key = serialization.load_pem_public_key(key_file.read())

message_bytes = message.encode('utf-8')
encrypted = public_key.encrypt(message_bytes, padding.PKCS1v15())
return base64.b64encode(encrypted).decode('utf-8')

AES-256 복호화

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64

def decrypt_aes256_base64(encrypted_data: str, key: str) -> str:
"""AES256으로 암호화된 base64 데이터 복호화"""
key_bytes = key.encode('utf-8')

# 32바이트 키 보장
if len(key_bytes) != 32:
if len(key_bytes) < 32:
key_bytes = key_bytes.ljust(32, b'\0')
else:
key_bytes = key_bytes[:32]

cipher_text = base64.b64decode(encrypted_data)
iv = key_bytes[:16] # 첫 16바이트를 IV로 사용

cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(cipher_text), AES.block_size)
return decrypted.decode('utf-8')